Compare commits

...
Author SHA1 Message Date
Sam Lantinga a96677bdf6 Updated to version 3.2.22 for release 2025-09-01 14:40:32 -07:00
Ryan C. Gordon 67f89d0a2b openslES: Patched to compile.
(whoops.)

(cherry picked from commit 7323104f97)
2025-09-01 11:10:33 -04:00
Ryan C. Gordon f6de8877ec openslES: OpenSL ES on Android only supports two formats, limit to that.
(Three with the floating point extension, which we use.)

This is according to:

https://developer.android.com/ndk/guides/audio/opensl/opensl-for-android

Previously, this would accept a request for Sint8 or Sint32 and disaster
would ensue.

Fixes #13779.

(cherry picked from commit 0b2a003a35)
2025-09-01 10:31:05 -04:00
Ozkan Sezer 7c189b1f17 cmake: revert commit 5d1bbd9 and change sse4.2 test
clang doesn't support -mcrc32 until version 14.0, therefore drop -mcrc32
use in sse 4.2 test, and change it to check _mm_cmpgt_epi64() instead of
_mm_crc32_u32(). without this, sse4.2 check was failing with clang <= 13

Fixes https://github.com/libsdl-org/SDL/pull/12223

(cherry picked from commit 875653658a)
2025-08-31 03:20:40 +03:00
Sam Lantinga a7947080c0 Fixed warnings building with Visual Studio
(cherry picked from commit 7c8df4ea52)
2025-08-30 10:16:11 -07:00
Sam Lantinga 08c82a3781 Fixed build
(cherry picked from commit 3cf2350f21)
2025-08-30 10:15:48 -07:00
Jordan Saunders 589aea50c2 Fix two uninitialized variables
Found when running in valgrind looking at another issue.

- RenderPass' depth_stencil_target
    Tripped in SDL_BindGPUFragmentSamplers when not binding a DS target

- VulkanCommandBuffer's swapchainRequested
    Tripped in VULKAN_Submit for the end transition barrier when
    creating an image. The field is only reset when reused, not on first
    use

(cherry picked from commit 265236d952)
2025-08-30 06:05:43 -07:00
Ozkan Sezer 72acd7c9df CI: add OpenBSD workflow
(cherry picked from commit c0e5fd55d2)
2025-08-30 14:22:24 +03:00
Frank Praznik 1a70d1158e fs: Fix OpenBSD path retrieval
Set the path start pointer to point to a valid string.

(cherry picked from commit fdfde42db1)
2025-08-30 14:21:24 +03:00
Frank Praznik ae915c6516 wayland: Add a sigtimedwait() implementation for OpenBSD
sigtimedwait() is an optional part of POSIX.1-2001, and OpenBSD doesn't implement it. Add a replacement implementation based on https://comp.unix.programmer.narkive.com/rEDH0sPT/sigtimedwait-implementation

(cherry picked from commit 1049426a76)
2025-08-30 14:21:00 +03:00
Xander 54d573332e Add SDL_SENSOR_COUNT to SDL_SensorType
(cherry picked from commit dc7a3a1219)
2025-08-29 07:31:25 -07:00
Matthew Zavislak 0204a69f6b Add elf alignment check for Android artifacts (#13818)
(cherry picked from commit 4f11feb708)
2025-08-28 16:31:25 -07:00
Susko3 b2689ff76a Avoid checking for HAVE_POSIX_SPAWN on Android
This makes the CMake build closer to SDL_build_config_android.h
as both will now use SDL_PROCESS_DUMMY.

(cherry picked from commit cd21bbe796)
2025-08-28 04:10:16 -07:00
Ozkan Sezer 611940fb80 cmake: fall back to -Wconversion if -Wfloat-conversion isn't available
... during checks for valid isinf/isinff/isnan/isnanf macros.

(cherry picked from commit 98bed62259)
2025-08-27 22:20:37 +03:00
Nintorch 16c0329a2a Add Emscripten joystick rumble support
Adds support for Emscripten (Web) joystick rumble support via EM_ASM_INT macros and HTML5's Gamepad API.

(cherry picked from commit 1fbed16cb0)
2025-08-25 12:59:15 -07:00
Nintorch 2743716132 Allow Android to ignore unnecessary joysticks
Previously, SDL_ShouldIgnoreJoystick wasn't being called for Android, and fingerprint sensors were recognized as joysticks.

(cherry picked from commit 1af7dfb0a7)
2025-08-25 11:23:34 -07:00
Colin Kinloch a744eee993 testffmpeg: avutil queue family version check
The `AVVulkanDeviceQueueFamily` struct was introduced by libavutil
59.34.100

(cherry picked from commit 81920b5db7)
2025-08-25 11:10:31 -07:00
Evan Hemsley 0e24267eb5 gpu: D3D12 only requires feature level 11_0 with Resource Binding Tier 2. (#13782)
We previously thought this wasn't possible because constant buffer offsets and
partial updates were unavailable, but we were reading the wrong table - this is
only the case for D3D11...

https://learn.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-devices-downlevel-intro

... while 12 doesn't list this feature at all:

https://learn.microsoft.com/en-us/windows/win32/direct3d12/hardware-feature-levels

We double checked and Jesse Natalie confirmed that this feature is required for
D3D12 even for 11_0 drivers. (Thanks Jesse!)

Additionally, D3D12 requires that UAVs are accessible from all shader stages,
meaning Tier 2 is enough to support the number of UAVs we need. Tier 1 could be
a property to lower the requirements, but that can be done later.
2025-08-22 14:07:58 -07:00
Wilson Jallet f4d6043aa4 GPU: Fix Vulkan indexing error for resolve attachment refs (#13768)
(cherry picked from commit 03b14f5211)
2025-08-19 12:13:23 -07:00
Petar Popovic 9fb9bd31a3 emscripten tests: fix warning: uninitialized variable
(cherry picked from commit 45feacf608)
2025-08-13 17:01:31 -07:00
ChaseKnowlden c3828bb0a3 Keep MSVC Flags Consistent across CMake runs
(cherry picked from commit 10478c59db)
2025-08-12 19:39:44 -07:00
Sam Lantinga 40371f0907 Support the "ambient" value for SDL_HINT_AUDIO_CATEGORY
Fixes https://github.com/libsdl-org/SDL/issues/13732

(cherry picked from commit 4725213eef)
2025-08-12 09:54:43 -07:00
Sylvain 94f9434564 Fixed bug #13493: Assertion failure at SDL_AddTouch with Android API 28
Java touch id should be -1 because it's reserved for internal SDL
synthetic events.
It should also not be 0, because this is SDL invalid value.

(cherry picked from commit 970c0bfe96)
2025-08-12 09:44:04 -07:00
Chase Knowlden bfaf247d30 Update NDK version to 28 (#13729)
* Update NDK version to 28 and add 16kb page size linker flags to x86_64

* Remove Android Linker Options

16kb page size is now the default since NDK r28c

* Update Android CI to use NDK 28

(cherry picked from commit 6e422e5ff2)
2025-08-12 07:46:27 -07:00
Beyley Cardellio 2287c43b59 GPU: Hold submit lock before waiting for device idle
(cherry picked from commit e699f3dca1)
2025-08-10 07:22:19 -07:00
Petar Popovic 15cc0f5f91 linux/SDL_syshaptic.c:SDL_SYS_HapticStopAll(): Fix return on error
(cherry picked from commit 43f3991398)
2025-08-09 09:28:02 -07:00
Anonymous Maarten 68e0108b1c release: build aarch64 libraries with 16kiB page size
[ci skip]

(cherry picked from commit 7017fbaa8e)
2025-08-09 05:23:43 +02:00
Mohamed Shazan 7b3796bc39 SDL_TriggerBreakpoint() will default to __debugbreak() on MinGW toolchain on windows
(cherry picked from commit f4c124e4bf)
2025-08-08 16:21:15 -07:00
Petar Popovic b5bc6d2cc4 SDL_SendJoystickVirtualSensorDataInner(): Fix max_sensor_events increment
(cherry picked from commit d9c20cfd0a)
2025-08-08 12:52:03 -07:00
Petar Popovic 0d1d4ea1f9 SDL_SetRenderDrawBlendMode(): Remove redundant param check
(cherry picked from commit b63c32e790)
2025-08-08 14:06:27 -04:00
Pino Toscano 1a48f897f2 ime: fcitx: use SDL_GetExeName() in GetAppName()
Use the existing SDL_GetExeName(), available for all the UNIX
platforms, in the internal GetAppName(); this has few advantanges:
- SDL_GetExeName() (and SDL_GetAppID() that builds on top of it) are
  used in various places already; since it caches the executable name,
  this may remove one extra read of the application name
- SDL_GetExeName() has a non-dummy implementation in more OSes than
  GetAppName(), thus providing a small improvement for this IME

As drive-by change: since SDL_GetExeName() provides a constant string,
there is no more need to allocate a new string in GetAppName(), which
is used as constant string anyway. Hence, return a constant string in
GetAppName() too.

(cherry picked from commit 248bcf6b29)
2025-08-07 13:58:27 -07:00
Simon McVittie 2b42789de6 Fix some typos detected by Debian's lintian QA tool
I assume the demoninator is a typo, rather than an indication that
someone has been playing too much Doom :-)

Signed-off-by: Simon McVittie <smcv@collabora.com>

(cherry picked from commit d83503f80e)
2025-08-07 13:55:44 -07:00
Simon McVittie b9c1da10ba hints: Rephrase documentation to improve grammar
"This thing allows to do something" is not really grammatically correct.
The closest rephrasing would be "allows one to do something" or "allows
the user to do something", but I think the passive voice reads more
naturally here.

Detected by Debian's lintian QA tool.

Signed-off-by: Simon McVittie <smcv@collabora.com>
(cherry picked from commit 40b941c826)
2025-08-07 13:55:44 -07:00
cosmonaut 56f5a76696 GPU: Fix uninitialized value in Vulkan command buffer structure
(cherry picked from commit fe6b2161bf)
2025-08-07 13:42:16 -07:00
Sam Lantinga c7e8977e60 Revert "Support Google Play 16 KB Page Size Requirement (#13470)"
This reverts commit edef6e66e9

If you need to support the Google Play 16 kiB page size requirement, the recommendation is to use NDK r28c or newer, which automatically aligns binaries correctly.
2025-08-07 11:41:43 -07:00
Pino Toscano e6ba3612db SDL_endian.h: extend Linux way for GNU libc
The currently used way to determine the endianness (i.e. include
<endian.h> and use the __BYTE_ORDER macro) is provided in general by
GNU libc. Thus, extend that to any platform/OS based on GNU libc.

(cherry picked from commit 561c99ee11)
2025-08-06 16:13:44 -07:00
Frank Praznik 5e77fb314c win32: Use the current flags to determine if NCCALCSIZE is required
SDL_GetWindowFlags() also ORs in pending flags, whereas the current state is needed here, particularly when creating/showing a window.

(cherry picked from commit cd0c660dea)
2025-08-05 18:49:41 -04:00
Frank Praznik 1a2841deb1 win32: Use STYLE_BORDERLESS when showing a pending fullscreen window
In addition to hiding the border on bordered windows that will immediately become fullscreen, The combination of flags used in STYLE_BORDERLESS_WINDOWED will still show the borders on borderless windows if the initial window size exactly matches the desktop, so STYLE_BORDERLESS must be used instead.

(cherry picked from commit 90a023007f)
2025-08-05 15:59:06 -04:00
Mathieu Eyraud 688637eca8 Fix condition for setting HDR properties
(cherry picked from commit a05aca51ec)
2025-08-05 09:26:12 -07:00
Frank Praznik 85d1d70ca1 cocoa: Wait for fullscreen spaces transitions to complete if switching to an exclusive mode
If attempting to switch to an exclusive mode while a fullscreen spaces transition is active, wait until the transition is complete before trying to apply the changes, or the window can wind up in a weird, broken state if a mode switch occurs while in a fullscreen space.

(cherry picked from commit f44a98729c)
2025-08-05 12:17:01 -04:00
Frank Praznik 09356c709a Revert "cocoa: Don't re-enter a fullscreen space if leaving to enter an exclusive mode"
This reverts commit 07b9e86d02.

It turns out that the problem is elsewhere, related to needing to block mode changes until spaces transitions are complete.
2025-08-04 23:51:47 -04:00
Frank Praznik 07b9e86d02 cocoa: Don't re-enter a fullscreen space if leaving to enter an exclusive mode
Doing so can leave the window in a weird, offset state.

(cherry picked from commit ee8f2861e7)
2025-08-04 22:16:22 -04:00
Sam Lantinga 8e46e5d8b4 Updated to version 3.2.21 for development 2025-08-04 11:54:34 -07:00
Sam Lantinga 96292a5b46 Updated to version 3.2.20 for release 2025-08-04 09:58:55 -07:00
Petar Popovic ffa618c00b SDL_LoadWAV_IO(): On error, set *audio_buf to NULL and *audio_len to 0
(cherry picked from commit 23e08f7807)
2025-08-03 13:44:37 -04:00
Petar Popovic 291b9b3c82 SDL_enabled_assert(): Use NULL istead of 0 to explicity initialize the pointer members of SDL_AssertData
(cherry picked from commit faf3bd9991)
2025-08-03 13:36:14 -04:00
Frank Praznik ec45117f0f x11: Filter mouse wheel events from "Master" devices
Discard wheel events from "Master" devices to avoid duplicates, as wheel events are stateless and can't be deduplicated.

(cherry picked from commit 51ce3f8c8d)
2025-08-02 18:57:44 -04:00
Frank Praznik 0d7aff9c56 GPU: Vulkan backend flags command buffer for cleanup when swapchain is requested
When skipping presentation due to the window being hidden, presentDataCount is not incremented on the command buffer, and subsequently the submitted command buffers will not be cleaned up as long as the window is hidden. This results in a lag spike when showing the window due to all previously submitted command buffers suddenly being cleaned up at once, and lag at shutdown due to an equivalent number of fences needing to be destroyed.

Instead of relying on presentDataCount to determine whether a command buffer should be cleaned up, use a flag, which is set under the appropriate circumstances.

(cherry picked from commit 42463569d5)
2025-08-02 09:24:21 -07:00
Petar Popovic d31b239288 Fix double-free warning in src/hidapi/linux/hid.c
(cherry picked from commit ae5ce258cf)
2025-08-02 07:09:12 -07:00
capehill b1cadf0e99 Fix SDL_BlitSurfaceScaled crash
SDL_BlitSurfaceScaled could crash when passed large coordinates, due
to final_dst.w or final_dst.h getting negative values.

(cherry picked from commit 1c5c3b1479)
2025-08-01 09:22:38 -07:00
Frank Praznik c1f67585e6 wayland: Cleanup an outdated conditional and comment
There may have been a reason for not attaching a null buffer when destroying a popup at some point in the past, but that is unnecessary now, as is the comment about ShowWindow crashing, as ShowWindow assures that a null buffer is attached before (re)creating the window.

(cherry picked from commit 550d95e04f)
2025-08-01 10:40:32 -04:00
A1029384756 93988e28c0 wayland: reorder surface destruction to avoid premature blanking
(cherry picked from commit 9034375d2f)
2025-08-01 10:40:32 -04:00
Matthew Zavislak edef6e66e9 Support Google Play 16 KB Page Size Requirement (#13470)
- See: https://developer.android.com/guide/practices/page-sizes#update-packaging
- Also, make min API uniform at 21 (from 16 and 23 in a few places)

(cherry picked from commit dc2c83c383)
2025-07-31 16:21:02 -07:00
Petar Popovic e3f47809c4 Fix potential memory leak in SDL_render_gles2.c
(cherry picked from commit 09221820f6)
2025-07-31 16:19:10 -07:00
cosmonaut f759e7ac59 GPU: Bail out of aquiring Vulkan swapchain if window is hidden
(cherry picked from commit c5edf4bd5b)
2025-07-31 16:03:19 -07:00
Frank Praznik 544eb2c5a9 wayland: Adjust popup adjoining check
The previous calculation could result in a window whose original position was positioned exactly corner-to-corner with the parent not being adjusted to be adjoining, and thus subject to spurious closure.

(cherry picked from commit b0cdb7143f)
2025-07-31 12:13:54 -04:00
Cheney Wang 30e3eba20a GPU: Fix wrong Vulkan swapchain size when retrying acquire
(cherry picked from commit d8ac51859e)
2025-07-30 15:35:23 -07:00
Wouter Wijsman f0e85a2a9c psp: fix audio not playing
(cherry picked from commit 3d1a28ccf2)
2025-07-30 13:11:23 -07:00
Thaddeus Crews 106af5b46a Define relevant macros when LACKS_ERRNO_H is true
(cherry picked from commit 3195980b49)
2025-07-30 09:11:22 -07:00
Stefan Schlosser 522716ed90 SDL_getenv.c: fix dynamic loading of environ symbol on FreeBSD
The current implementation uses the returned address of the `dlsym` function
directly to load the `environ` symbol. But this function doesn't return the
address to the symbol itself, instead it returns the address to the location
where the actual address is stored, i.e. it's an additional indirection.
Consequently, the implementation fails to load and process the environment
variables successfully.

One example where this error shows up is in the `Dialog API`: in an `X11`
environment, the `zenity` driver requires access to the user's `DISPLAY` and
`XAUTHORITY` environment variables. Because these variables aren't transfered
to the `zenity` process, no dialogs are shown. This can be exercised in the
`test/testdialog.c` testprogram.

The fix changes the indirection level of the `dlsym` call from `char **` to
`char ***`, does a `NULL`-check in case the call failed, and returns the
dereferenced actual adress to the `environ` symbol.

(cherry picked from commit 10458f2cac)
2025-07-30 07:06:54 -07:00
Evan Hemsley a65fbb0211 GPU: Fix incorrect block size when D3D12 uniform buffer is rotated (#13469)
(cherry picked from commit 07af4b237b)
2025-07-29 15:51:58 -07:00
Petar Popovic 46ec859bd1 Fix two use-after-free warnings
(cherry picked from commit f27dbb22f0)
2025-07-29 12:29:34 -07:00
Xen 2a7aa4eae4 Update SDL_clipboard.h
Typo fixes and a small addition to SDL_SetClipboardData about mime_type list usage clarity.

(cherry picked from commit b3ba1c159e)
2025-07-28 11:59:34 -07:00
Dan Andrus c31ddf021e Check NSWindow::isVisible before sending SDL_WINDOWEVENT_RESTORED during Cocoa_WindowListener::windowDidResize
(cherry picked from commit 30f0aeb26a)
2025-07-28 14:47:45 -04:00
Shootfast eaa2a8239f Fixed typo in SDL_scancode.h
The backslash/vertical line key is between the left shift and "Z" key on ISO keyboards

(cherry picked from commit 507ee033cc)
2025-07-27 19:58:45 -07:00
Brenton Bostick d313ecb737 Fix warning on Android arm-v7
Building SDL for armeabi-v7a gives this warning:
```
SDL/src/audio/SDL_audiotypecvt.c:541:14: warning: '#pragma FENV_ACCESS' is not supported on this target - ignored [-Wignored-pragmas]
  541 | #pragma STDC FENV_ACCESS ON
```

(cherry picked from commit ed4de7aeed)
2025-07-27 08:16:21 -07:00
Petar Popovic 64b2af0340 SDL_gpu.c: Fixed deref-before-check warning
(cherry picked from commit 6a5af95364)
2025-07-26 12:08:57 -07:00
Anonymous Maarten 58d0702948 ci+n3ds: avoid apt-get package manager
- use Unix Makefiles (with parallelization) CMake generator
- use binutils strings binary from devkitpro

(cherry picked from commit e6d200e51c)
2025-07-26 16:06:36 +02:00
Sam Lantinga 707717e94b Reverted: Added Steam Virtual Gamepad support to the GameInput driver
This version of SDL doesn't support newer GameInput versions required for this feature.
2025-07-24 14:00:20 -07:00
Sam Lantinga a140bba55a Fixed building with GameInput v1.0
(cherry picked from commit e5d57d8ad6)
2025-07-24 10:52:28 -07:00
Sam Lantinga f4ddacacd0 Fixed building with GameInput v1.0
(cherry picked from commit 0ee0fe1572)
2025-07-24 10:43:05 -07:00
Sam Lantinga ebba656bdb Added Steam Virtual Gamepad support to the GameInput driver
(cherry picked from commit 66dad9c21f)
2025-07-24 10:38:02 -07:00
Sam Lantinga b78c61d67a Fixed double SDL_EVENT_GAMEPAD_ADDED for controllers with automatic gamepad mappings
(cherry picked from commit 6babade758)
2025-07-24 10:38:02 -07:00
L zard 4210aa61e1 build_config_windows: define HAVE_STDARG/STDDEF_H outside of
condition.
They are defined in both `#if HAVE_LIBC` and its `#else` anyway.
[sdl-ci-filter msvc-*]

(cherry picked from commit ea995b1694)
2025-07-21 14:45:19 -07:00
L zard d8a345d924 build_config_windows: fix HAVE_VSSCANF defined regardless of MSVC version.
[sdl-ci-filter msvc-*]

(cherry picked from commit a977a11fa6)
2025-07-21 14:45:19 -07:00
Acclution b8dc9767da GPU: Fix Vulkan compute uniform descriptor not being marked as set (#13389)
(cherry picked from commit 8bd29f7ca3)
2025-07-18 15:30:05 -07:00
BurntRanch 1ab01b9367 Clarify SDL_GPUVertexBufferDescription.pitch comment (#13381)
(cherry picked from commit ee6d8f78f4)
2025-07-17 08:55:04 -07:00
Sam Lantinga ee371ff740 Fixed crash if a clipboard event was sent with video uninitialized
This can happen if you're using SDL on Android without using the video subsystem.

(cherry picked from commit 855d28e97a)
2025-07-17 08:48:00 -07:00
Evan Hemsley ef58dd77ca GPU: Clean up properties in SDL_ReleaseGPUTexture (#13378) 2025-07-17 00:23:52 -07:00
Ryan C. Gordon e6a7121904 audio: Binding an SDL_AudioStream will set missing formats.
It _must_ have the format set for the opposite side from the device (so
playback needs the src format set, and recording needs the dst format set),
since the stream gets mangled by the device thread if not. So if it has never
been set (stream created with NULL audiospec), just set it to match the device.
If the stream is just meant to buffer and not convert, this is desired
behavior, even if it didn't also fix a bug.

Binding the audio stream will always set the device side's format, as usual;
this does not need to be set by the caller at all.

Fixes #13363.

(cherry picked from commit f2ae6503c0)
2025-07-15 06:44:12 -04:00
Sam Lantinga a6ed8ab59d Updated to version 3.2.19 for development 2025-07-14 11:44:22 -07:00
Sam Lantinga bd40d0ded1 Removed the Mayflash GameCube adapter from the PS3 controller list
(cherry picked from commit 277f91c317)
2025-07-14 11:30:46 -07:00
Andon M. Coleman 68bfcb6c54 Allow 1 kHz sample rate for DualSense Edge over USB
DualSense Edge natively reports at 1 kHz for all connection types, but gyro sample rate was limited to 250 Hz for USB.

(cherry picked from commit a07cf3ecdc)
2025-07-14 10:02:46 -07:00
Josh Dowell 0d01efca52 windows: Fix crash when using a system that reports itself as Windows 17763 or newer, but is missing many of the newer dark mode window functions (Linux Mint Cinnamon w/ Proton 7.0.6)
(cherry picked from commit 0a50b798bf)
2025-07-13 20:10:26 -07:00
Kyle Sylvestre 0e65e04ce1 remove spoofed SDL_HelperWindow when SDL_VIDEO is off
(cherry picked from commit 0f061ff154)
2025-07-12 07:48:56 -07:00
Kyle Sylvestre 58d351fe98 check SDL_PLATFORM_WINDOWS instead of SDL_VIDEO_DRIVER_WINDOWS when using SDL_HelperWindow
(cherry picked from commit d42217ba26)
2025-07-12 07:48:56 -07:00
Kyle Sylvestre 9b71f18141 move SDL_HelperWindow outside of video
move to SDL_window.c to prevent relying on SDL_VIDEO

(cherry picked from commit a190e3b514)
2025-07-12 07:48:56 -07:00
Anonymous Maarten 554f08bac3 ci: build MSVC release binary on windows-2025 2025-07-12 01:25:08 +02:00
Sam Lantinga 913813a933 Updated to version 3.2.18 for release 2025-07-11 15:56:55 -07:00
Ryan C. Gordon 4e34c771e4 Revert "windows: Use wglSwapLayerBuffers if available."
This reverts commit b8ee44ca6a.

This is reverting a cherry-pick. It's probably too risky for a 3.2.x release,
but we'll let it marinate on main, for 3.4.0.
2025-07-11 18:25:14 -04:00
Ryan C. Gordon 9995174e68 gpu: Fixed uninitialized variable in SDL_AcquireGPUCommandBuffer().
Fixes #13191.

(cherry picked from commit 190afc0f4f)
2025-07-11 18:23:15 -04:00
Ryan C. Gordon 5a0197d430 wasapi: Force enumerated audio devices to report themselves as float32 format.
This is what they'll end up being when used through WASAPI in shared mode,
regardless of what the hardware actually expects.

Reference Issue #12914.

(cherry picked from commit a81cf566f4)
2025-07-11 18:23:01 -04:00
Sam Lantinga 4a55143e15 Fixed build
(cherry picked from commit 92e8224d32)
2025-07-11 14:12:27 -07:00
Sam Lantinga 87c9bc1b1f Fixed long delay when enumerating the Razer Huntsman keyboard
Fixes https://github.com/libsdl-org/SDL/issues/13236

(cherry picked from commit 0b2e389ee3)
2025-07-11 14:12:27 -07:00
Sam Lantinga 16a57b70f7 Set hwndTarget to NULL when unregistering raw input
Fixes https://github.com/libsdl-org/SDL/issues/13335

(cherry picked from commit 937e8d55a4)
2025-07-11 12:14:50 -07:00
Aleksey Sakovets 69564cd0b1 README-macos.md: replace old API calls
(cherry picked from commit 6386781351)
2025-07-11 12:08:58 -07:00
Ryan C. Gordon da648b00e7 cocoa: Don't minimize fullscreen windows for a modal file dialog.
macOS sends a focus loss event when the dialog is created, which causes SDL
to try to minimize the window, which confuses the entire system. So in this
special case, don't do the minimization.

Fixes #13168.

(cherry picked from commit 9af93abd4f)
2025-07-11 15:06:10 -04:00
Sam Lantinga 5886d90308 Fixed long delay when enumerating the Razer Huntsman keyboard
Fixes https://github.com/libsdl-org/SDL/issues/13236

(cherry picked from commit f199aafaeb)
2025-07-11 11:56:06 -07:00
Ryan C. Gordon e84df0cad1 x11: Avoid duplicate mouse events when using a pen device.
Fixes #12968.

(cherry picked from commit 72f4dd17be)
2025-07-11 14:31:07 -04:00
Frank Praznik e482904111 Add support for non-constrained and non-grabbing popups
By default, popups are automatically constrained to be completely within display bounds, so as not to cut off information and result in an unusable menu, or unreadable tooltip. In some cases, however, this is not wanted, so a property to toggle this behavior is added.

There are also cases where the client may not want a popup menu to implicitly grab the keyboard focus, as is the default behavior, so popup menus now respect the focusable flag/property, as well as being able to toggle focus grabbing via SDL_SetWindowFocusable().

(cherry picked from commit b871ac0d97)
2025-07-11 14:26:51 -04:00
Ryan C. Gordon b8ee44ca6a windows: Use wglSwapLayerBuffers if available.
It apparently works better (or can work better?) on multimonitor setups
than SwapBuffers.

This should be available back to Windows 95, but just in case, it falls
back to standard SwapBuffers if not available.

Fixes #13269.

(cherry picked from commit f286558bae)
2025-07-11 13:25:18 -04:00
Anonymous Maarten 4a4abe4240 cmake: remove /RTC1 from CXX flags when building with SDL_LIBC=OFF
(cherry picked from commit cfb8e591cb)
2025-07-11 10:00:22 -07:00
Wouter Wijsman fe47f5cc30 PSP: Truncate thread name when passing to sceKernelCreateThread
(cherry picked from commit c64518f300)
2025-07-11 10:00:07 -07:00
Ryan C. Gordon 5b64be0810 docs: Documentation for SDL_Swap64 was reporting the wrong return type.
Fixes #13309.

(cherry picked from commit 530639aa4a)
2025-07-11 09:59:13 -07:00
Ryan C. Gordon 17656d051b cocoa: Don't use trick of briefly focusing the Dock on newer macOS releases.
On newer systems, the trick isn't necessary, and if you do it, if the user is
moving the mouse when launching the app, it'll show a hidden Dock.

Fixes #10340.

(cherry picked from commit 279dabfc96)
2025-07-10 15:54:25 -04:00
Ozkan Sezer 233fce456a fix ARM64 linkage with Visual Studio >= 17.14 when SDL_LIBC is disabled
Reference issue:  https://github.com/libsdl-org/SDL/issues/13254

(cherry picked from commit 2fb6abb9ad)
(cherry picked from commit fb0e03f262)
2025-07-09 01:32:00 +03:00
Frank Praznik 5290bb036c wayland: Ensure that the xdg_surface is always configured after creation
The spec states that xdg_surface must have seen an initial configure event before attaching a buffer, however, this was only being done when initially showing the window, and not after show->hide->show cycle.

Always wait for the initial configure event when (re)creating an xdg_surface as part of the show window sequence.

(cherry picked from commit ecdc6f2adb)
2025-07-05 12:10:28 -04:00
WillyJL 2bff72b4f6 SDL3 GPU: Fix -Wbool-conversion warnings
(cherry picked from commit 4eff36ef53)
2025-06-29 13:33:56 -04:00
Anonymous Maarten 08ebeaee5c cmake: Android always needs a native HIDAPI implementation
(cherry picked from commit 89eef1bd34)
2025-06-26 15:43:29 -07:00
Caleb Heuer 12b56f5447 Allow overriding SDL_FORK_MESSAGEBOX in build environment
(cherry picked from commit cd98b66114)
2025-06-26 10:49:48 -07:00
Frank Praznik 165b86e7b7 x11: Always update the borders on frame extent events
Always update the border sizes on frame extent events, or they can incorrectly still be zero if followed by a PropertyNotify event when leaving fullscreen.

Fixes sending the correct restored window size when leaving fullscreen in fvwm.

(cherry picked from commit 0ac1241b7a)
2025-06-26 11:53:32 -04:00
Sam Lantinga 608101a185 Update the viewport when logical presentation changes
Fixes https://github.com/libsdl-org/SDL/issues/13256

(cherry picked from commit 727b4924c8)
2025-06-25 09:59:13 -07:00
Paul Vick 554bee6aae Fix #13276: Crash in SDL_GetAudioDeviceChannelMap
(cherry picked from commit de6a23028a)
2025-06-25 09:59:07 -07:00
Rémi Verschelde 3e0ce51067 joystick: Fix MSVC errors C2099 with /fp:strict
(cherry picked from commit db3a35e9bc)
2025-06-24 07:32:26 -07:00
Ozkan Sezer 7261c43342 alsa: change an SDL_LogError into SDL_LogDebug.
it is informational only and seeing ERROR on the terminal was confusing

(cherry picked from commit af8bee2dd1)
2025-06-22 21:05:10 -07:00
Marcin Serwin ad57c6ea37 test: Fix resource paths in testtray
Signed-off-by: Marcin Serwin <marcin@serwin.dev>
(cherry picked from commit bbc674b9e7)
2025-06-22 21:03:55 -07:00
mitchellcairns caecff650d Resolve bug for calibration Nintendo Switch Pro Controller (#13260)
Resolves a bug which prevents the stored calibration data from loading, only allowing loading of factory-installed calibration data

(cherry picked from commit 796961acec)
2025-06-22 21:00:01 -07:00
Mitch Cairns f6300be4b2 Fixed Nintendo Switch thumbstick calibration
(cherry picked from commit 3a6f9e01f8)
2025-06-22 15:27:30 -07:00
Sam Lantinga bde5687a3c Fixed Nintendo Switch Pro thumbstick calibration
Fixes https://github.com/libsdl-org/SDL/issues/13246

(cherry picked from commit 038a3806eb)
2025-06-21 19:57:04 -07:00
Sam Lantinga 0f3504f78d Updated testffmpeg for ffmpeg 7.1
(cherry picked from commit e6c2649afc)
2025-06-21 08:49:43 -07:00
Sam Lantinga 0aaa0321cc Fixed warning C5286: implicit conversion from enum type 'VkFilter' to enum type 'SDL_ScaleMode' 2025-06-21 07:41:20 -07:00
Josh Dowell caaaf52583 win32: Invalidate window message mouse button flags when reading buttons from raw input or GameInput
SDL2 would set a high bit in the mouse button flags to indicate when raw input had been read from, without this, if you hold down a mouse button and left raw input mode (leaving relative mode) the button would remain partially stuck, and would require two clicks to start producing mouse down events again.
SDL3's raw input code was refactored to not use the mouse button flags, but forgot to invalidate the flags, causing this bug to manifest.

(cherry picked from commit 6aedc488d3)
2025-06-21 07:29:05 -07:00
Ozkan Sezer 56449f167d hidapi/libusb: disable C5287 warning in MSVC builds
A quick search implies that it is a bogus warning:
https://www.google.com/search?q=visual+studio+C5287

(cherry picked from commit 81e3066303)
2025-06-21 07:16:36 -07:00
Ryan C. Gordon c7325228dc audio: Enumerating audio devices will skip zombie devices still in the hash.
(cherry picked from commit eb04219efe)
2025-06-20 14:49:32 -07:00
Sam Lantinga 079967afa5 Clarify that SDL_GetAudioStreamDevice() returns the logical device.
(cherry picked from commit c19ad189dc)
2025-06-20 14:01:32 -07:00
Lilian Gimenez 2ed55b614c Fix support for F21 to F24 scancodes on Linux
(cherry picked from commit e4e29b8601)
2025-06-20 09:07:27 -07:00
Frank Praznik 28721e3cd2 test: Fix a window parenting bug in testmodal
(cherry picked from commit 390fe65323)
2025-06-18 09:27:03 -04:00
Frank Praznik 9d9845d063 video: Explicitly disallow setting the parent of a window to itself
Doing so causes a cycle in the window hierarchy tree graph, which leads to infinite recursion when destroying the windows.

(cherry picked from commit ca9b7c8ea3)
2025-06-18 09:27:03 -04:00
ceski a96dc76831 Read Switch controller gyro/accel sensitivity coeffs (SDL3)
These vary by controller, so using the stored values should improve the accuracy of the sensor data.

(cherry picked from commit 558a89fdb6)
2025-06-13 12:18:43 -07:00
e4m2 ad8e517227 Tweak Vulkan include guard check and 64-bit platform defines (#13210)
(cherry picked from commit c5b1341757)
2025-06-12 09:32:32 -07:00
Sam Lantinga 8d578d590f Fixed replacing existing specific gamepad mappings
If the first mapping we see doesn't have a CRC, continue looking for another exact CRC match.

Fixes testautomation --filter TestVirtualJoystick

(cherry picked from commit 5826966873)
2025-06-06 09:55:04 -07:00
Sam Lantinga 6b4a211374 Added support for the ZEROPLUS P4 Wired Gamepad
(cherry picked from commit f90a21483c)
2025-06-06 09:27:17 -07:00
Sam Lantinga 55b023c961 Remove the CRC from automatically generated gamepad mappings
Fixes https://github.com/libsdl-org/SDL/issues/13127

(cherry picked from commit 638acdc02a)
2025-06-06 09:25:19 -07:00
Frank Praznik e2d0fe3e2f x11: Resize fixed-size windows after mapping on xmonad
XMonad ignores size hints and shrinks the client area to overlay borders on fixed-size windows, even if no borders were requested, resulting in the window client area being smaller than requested. Calling XResizeWindow after mapping seems to fix it, even though resizing fixed-size windows in this manner doesn't work on any other window manager.

(cherry picked from commit 45eb6310a8)
2025-06-06 11:35:56 -04:00
Frank Praznik 6b56ff7a97 win32: Ensure that text input is initially disabled when creating a window
Windows seems to implicitly enable IME text input on windows created while an IME is active, which causes the IME suggestion window to pop up when keys are pressed, even if a client never explicitly enabled it. Ensure that IME support is initially disabled on new windows; SDL will enable it at a later time, if required.

(cherry picked from commit 22fa45b3c1)
2025-06-05 12:21:49 -04:00
Ethan Lee 67f796ebde gdk: Ignore focus loss events caused by text input showing the OSK 2025-06-04 09:41:06 -04:00
Sam Lantinga 06da7490fc Added support for the NACON Revolution X Unlimited controller on macOS
This adds support for the controller in Bluetooth mode.

Fixes https://github.com/libsdl-org/SDL/issues/13143

(cherry picked from commit 6622f4e1ea)
2025-06-03 15:08:11 -07:00
Sam Lantinga af83c442d3 Fixed input from the MayFlash GameCube adapter with version 7 firmware
(cherry picked from commit 7457857304)
2025-06-03 11:14:09 -07:00
Sam Lantinga d726e98596 Updated to version 3.2.17 for development 2025-06-02 15:57:36 -07:00
Caleb Cornett c9a6709bd2 gpu: Add BC2_RGBA_UNORM_SRGB to GetBlockWidth/Height functions 2025-06-02 13:53:42 -07:00
Evan Hemsley 25816bea41 GPU: Binding validation and prevent null dereference if expected binding is missing (#13164) 2025-06-02 13:40:40 -07:00
Sam Lantinga e0f6e96da0 Use HEAPU8.set rather than Module.HEAPU8.set (thanks @sbc100!)
The Module object is the external interface to the application, internal symbols like HEAPU8 don't need to be exported to be used and usage should not be prefixed with Module.

Fixes https://github.com/libsdl-org/SDL/issues/13156
Closes https://github.com/libsdl-org/SDL/pull/13157

(cherry picked from commit cf6c42e6e6)
2025-06-02 09:48:55 -07:00
Sam Lantinga 57de46ae7e Mark gamepads as invalid if they can't be opened
Fixes https://github.com/libsdl-org/SDL/issues/13129

(cherry picked from commit 4b0f48c4cf)
2025-06-02 09:25:10 -07:00
Sam Lantinga 59693c8996 Updated to version 3.2.16 for release 2025-06-01 14:37:23 -07:00
Ryan C. Gordon f0efffc093 x11: Be a little less aggressive with Xinput2IsInitialized checks.
Just in case this ever get deinitialized sooner, we'd still like to SDL_free()
things on shutdown, etc.

Reference PR #13148.

(cherry picked from commit 9e0d9f30a7)
2025-06-01 10:15:54 -04:00
Mason Remaley 1b41cd759c Checks if xinput is loaded before trying to call xinput functions
(cherry picked from commit 57b6e6c7f9)
2025-06-01 10:15:47 -04:00
Ryan C. Gordon d42a1402e8 audio: corrected comment about device format minimums.
(cherry picked from commit ac3ab026fe)
2025-06-01 03:01:47 -04:00
Ryan C. Gordon 5c44678d55 audio: Opened device spec must be >= simple minimums, not device's defaults.
Fixes #13159.

(cherry picked from commit 83cc3bc234)
2025-06-01 02:58:41 -04:00
Ryan C. Gordon 0638fd58ce pulseaudio: Request more recording data per-fragment.
This seems to help some devices that can't keep up with smaller fragment sizes
for whatever reason.

Fixes #13110.

(cherry picked from commit 14a4ae521a)
2025-06-01 02:48:49 -04:00
Ryan C. Gordon cb662b6730 cocoa: add explicit tracking areas to the window.
This makes sure we get reliable mouse enter/exit events from the system on
older macOS releases.

Newer releases don't have this problem--my assumption is that Cocoa has a
more aggressive default tracking area installed for some newer UI feature.

For 3.2.16, we'll use the explicit tracking area on older macOSes only, but
I'll remove that check in revision control for newer OSes and see what
happens.

Fixes #12725.

(cherry picked from commit f61d956a04)
2025-05-31 14:45:43 -04:00
Caleb Heuer e874c7515e Pass text input rect to steam deck keyboard invocation
(cherry picked from commit 51dfca813b)
2025-05-30 09:54:53 -07:00
Ethan Lee 2ba797576b storage: Declare a private bootstrap for NDA user storage 2025-05-30 12:15:43 -04:00
Sam Lantinga 180b454d61 kmsdrm: fixed creating GBM surfaces on NVIDIA cards
(cherry picked from commit fc1c0618de)
2025-05-29 11:20:44 -07:00
DracoRooks 6ce7ae77b1 Update SDL_pixels.h
Added an opening bracket in line 520, in the comment block of SDL_PixelFormat. Simple addition to the readability of documentation.

(cherry picked from commit 03a6d98aee)
2025-05-29 11:03:54 -07:00
Sam Lantinga abbaf95cf0 Added macros to push/pop error messages while cleaning up
(cherry picked from commit 885e611f3c)
2025-05-29 10:54:46 -07:00
Sam Lantinga 1081b70951 Fixed typos
(cherry picked from commit 61d105247e)
2025-05-29 10:54:46 -07:00
Sam Lantinga 4f51f956ad Updated SDL_StretchSurface() documentation
Fixes https://github.com/libsdl-org/SDL/issues/13135

(cherry picked from commit 7db0ac7380)
2025-05-29 09:09:29 -07:00
Sam Lantinga b076f4b590 Removed obsolete documentation
(cherry picked from commit 737b9e117d)
2025-05-28 15:57:23 -07:00
Sam Lantinga 91180f8cb4 Disable SDL_HINT_JOYSTICK_RAWINPUT by default
Windows can get in a state when it stops reporting raw input events for game controllers until reboot.

The downside of this change is that we lose support for trigger rumble and are limited to 4 controllers again, but if that's important for your application you can use SDL_SetHint(SDL_HINT_JOYSTICK_RAWINPUT, true) to enable this functionality.

Fixes https://github.com/libsdl-org/SDL/issues/13047

(cherry picked from commit aa870d511e)
2025-05-27 09:51:58 -07:00
Ethan Lee 99aa859362 gpu: Xbox buildfix 2025-05-27 12:42:46 -04:00
Frank Praznik 31267feb03 wayland: Use raw timestamps to calculate the elapsed repeat time on a key up event
Using processed timestamps can result in anomalies that cause excessive repeat events, and hard caps can cause issues.

In the key event handler, use the raw elapsed time to calculate any remaining repeat events to avoid the artifacts that can result from using processed timestamps.

The Wayland key repeat rate ranges from 0 to 1000 per second, so millisecond resolution doesn't lose any precision.

(cherry picked from commit e3d44cdd51)
2025-05-27 11:18:56 -04:00
Sander Ledegen 6a5bac72cb PSP fullscreen is the only mode (#13125)
(cherry picked from commit 9b025e3cab)
2025-05-26 10:32:13 -07:00
Ozkan Sezer 2ed5062950 SDL_video.c: remove two stray line continuation chars .
(cherry picked from commit 25db127450)
2025-05-26 01:45:50 +03:00
Christian Kündig 0b0b02c5a1 emscripten: Proxy Emscripten_GetSystemTheme and EMSCRIPTENAUDIO_OpenDevice to the main thread.
(cherry picked from commit 168d1a9253)
2025-05-25 13:50:19 -07:00
mattbsage 28c71368a1 Clean up INTERFACE_COMPILE_OPTIONS
The extra text causes Meson/Ninja builds to fail as headers are not found.

(cherry picked from commit f62572344f)
2025-05-24 19:13:41 -07:00
Frank Praznik 25bd4285ab x11: Assume the window was mapped after showing
Not all window managers send a MapNotify or PropertyNotify event when the window is shown, so assume that it was mapped and set the flag accordingly.

(cherry picked from commit b70919ecd9)
2025-05-24 10:00:43 -04:00
Frank Praznik 180171cad6 x11: Always send fullscreen dimensions except on XWayland
More non-compositing window managers than just openbox seem to need this, so always force sending the window position and dimensions when entering/leaving fullscreen. If they are wrong, they will be immediately overwritten by the correct dimensions from a subsequent ConfigureNotify event.

This is disabled on XWayland, as it seems to cause hitching on some compositors.

(cherry picked from commit 0657ece55d)
2025-05-24 10:00:43 -04:00
Sam Lantinga bc3eeecf7f Set the initial axis values for HIDAPI and XInput controllers
Fixes https://github.com/libsdl-org/SDL/issues/13020

(cherry picked from commit 1f6b5c681d)
2025-05-23 12:09:58 -07:00
Frank Praznik 9178d14519 x11: Include the XTest header when needed
Fixes building when statically linking.

(cherry picked from commit fdc4f8fa39)
2025-05-23 13:12:47 -04:00
Ivan Epifanov 6cd35f5b72 VITA: support only fullscreen windows. Fixes #13079
(cherry picked from commit 2b4d61e4a6)
2025-05-23 08:45:49 -07:00
kyle-sylvestre 72d5eb0ecb fix error handling in WideCharToMultiByte
(cherry picked from commit ead32c706d)
2025-05-22 15:25:58 -07:00
kyle-sylvestre 5cf924420d bugfix advancing UTF-8 length in UTF-16 string
(cherry picked from commit 8ddb074889)
2025-05-22 15:25:58 -07:00
Ryan C. Gordon 290574e6f6 stdinc: Corrected documentation for SDL_atan2 and SDL_atan2f.
Fixes #13099.

(cherry picked from commit 8d9a4fe843)
2025-05-22 09:52:51 -04:00
Frank Praznik d9db975b4b wayland: Use SDL_memcpy instead of SDL_copyp to copy the repeated text string
SDL_copyp is not intended to copy arrays. Use SDL_memcpy with the explicit size instead.

(cherry picked from commit abcfa1b7de)
2025-05-21 20:39:03 -04:00
Matteo Hausner e5c0e5efa7 Fix #13083 segfault in SDL_RemoveTrayEntry() for submenu entries
Use `g_object_ref_sink()` in `SDL_CreateTraySubmenu()` as introduced with
3be67ced64 for the top-level menu.

(cherry picked from commit 22828d5f2a)
2025-05-21 13:32:47 -07:00
Sam Lantinga 26a1aae098 Fixed the Bluetooth flag for the combined Joy-Con controller
(cherry picked from commit 264eb8d440)
2025-05-21 13:30:30 -07:00
Frank Praznik ab114490fc wayland: Cap the max key repeat elapsed time
Cap the elapsed time to something sane in case the compositor sends a bad timestamp, which can result it in it looking like the key has been pressed for a *very* long time, bringing everything to a halt while it tries to enqueue all the repeat events.

(cherry picked from commit 05f779f61e)
2025-05-21 12:20:31 -04:00
kyle-sylvestre 9546c54286 use SDL style - else on same line as closing brace
(cherry picked from commit b8e055ce64)
2025-05-20 17:13:47 -07:00
kyle-sylvestre 4d3cdb70b5 get preferred locales on android
(cherry picked from commit 8e22194217)
2025-05-20 17:13:47 -07:00
Anthony Fisher a66816a72f gpu/d3d12: Acknowledge that we've bound vertex buffers (#13088) 2025-05-20 16:34:27 -04:00
Francisco Javier Trujillo Mata c925f72562 Fix wrong callback type
(cherry picked from commit c89357bf60)
2025-05-20 11:11:01 -07:00
Logan ef97329f41 GPU: Update D3D12 to create multisample textures with default MSAA alignment
(cherry picked from commit f4942b3eae)
2025-05-20 11:07:54 -07:00
Frank Praznik 195f709eda wayland: Set the text input cursor rect properly
The text input cursor should reflect the cursor position, not the entire text input rect. Set it correctly so that IME chooser dialogs appear in the correct location.

(cherry-picked from commit c7549eb0b6)
2025-05-20 13:42:21 -04:00
cosmonaut eb57d94ec5 GPU: Add missing compute-writeable texture formats 2025-05-19 18:11:06 -07:00
Sam Lantinga d6212ae839 Fixed rare crash trying to interrupt SDL_WaitEvent()
Fixes https://github.com/libsdl-org/SDL/issues/12797

(cherry picked from commit 992e4c59bd)
2025-05-19 14:16:25 -07:00
Frank Praznik b494897b3d wayland: Don't add the nanosecond timestamp offset to the pre-conversion millisecond value
(cherry picked from commit 6c61a94a4b)
2025-05-19 14:00:12 -04:00
Sam Lantinga 559d4415eb Fixed touch not being delivered as mouse events by default on Vita
Closes https://github.com/libsdl-org/SDL/pull/13070

(cherry picked from commit 25f2376e79)
2025-05-19 08:33:28 -07:00
Joe [ReRezd] 49e9134774 Fix: GameCube controller adapter hotplug not working
SDL_PrivateJoystickAdded was called before setting the InstanceId in the adapters ctx->joysticks array.  This would eventually broadcast the SDL_EVENT_JOYSTICK_ADDED event with the new InstanceId, if your program listens for the added events and opens joysticks at that point it would always fail because there would be no matching InstanceId in the ctx->joysticks array.

(cherry picked from commit afd1e51023)
2025-05-19 08:25:16 -07:00
Logan 9571b0ece8 GPU: Update to set supported shader formats inside CreateDevice
(cherry picked from commit 8289656a4e)
2025-05-18 18:33:07 -07:00
danginsburg b55cfaf90b Fix #13057 - fixes bug with NSEventTypeMouseMoved having a NULL window causing us to suppress future mouse move events because the window was considered out of focus.
(cherry picked from commit 968222e74f)
2025-05-16 17:07:49 -07:00
ScolderCreations 509168856f Fix reference to nonexistent "README-3ds.md"
(cherry picked from commit d16371b923)
2025-05-15 11:23:17 -07:00
Stéphane GINIER 24fa2722c3 MacOS: fix cocoa clipboard text
Adjust Cocoa_SetClipboardData so that SetClipboardText text can be pasted outside SDL

(cherry picked from commit 945eb6dc87)
2025-05-15 10:54:15 -07:00
Evan Hemsley 142700f909 GPU: Check that a texture format is valid for compute writes (#13044) 2025-05-14 16:25:24 -07:00
Evan Hemsley f3611681df GPU: Always return NULL if beginning a pass fails an assert check 2025-05-14 15:23:57 -07:00
Sam Lantinga 7f0a5d6a10 Updated to version 3.2.15 for development 2025-05-14 13:08:44 -07:00
cosmonaut 2001cc15d5 GPU: Debug mode layer and level index checks 2025-05-14 12:25:18 -07:00
152 changed files with 2574 additions and 1313 deletions

No files matched your search

+22 -3
View File
@@ -54,6 +54,7 @@ class SdlPlatform(Enum):
Riscos = "riscos"
FreeBSD = "freebsd"
NetBSD = "netbsd"
OpenBSD = "openbsd"
class Msys2Platform(Enum):
@@ -137,6 +138,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 +176,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 +225,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 +259,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 +294,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 != ""}
@@ -550,6 +556,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 +685,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 +726,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 +750,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}")
+13 -5
View File
@@ -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') }}
@@ -428,4 +436,4 @@ jobs:
with:
if-no-files-found: error
name: '${{ matrix.platform.artifact }}-apks'
path: build/test/*.apk
path: build/test/*.apk
+2 -2
View File
@@ -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:
+39 -35
View File
@@ -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.22")
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
set(SDL3_MAINPROJECT ON)
@@ -183,26 +183,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)
@@ -421,6 +401,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 +637,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")
@@ -753,19 +761,14 @@ 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("
#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)
cmake_pop_check_state()
@@ -1052,8 +1055,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 +1096,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 +1342,7 @@ if(ANDROID)
set(HAVE_SDL_HAPTIC TRUE)
endif()
if(SDL_HIDAPI)
CheckHIDAPI()
endif()
CheckHIDAPI()
if(SDL_JOYSTICK)
set(SDL_JOYSTICK_ANDROID 1)
@@ -2954,7 +2958,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>
+2 -2
View File
@@ -19,10 +19,10 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>3.2.14</string>
<string>3.2.22</string>
<key>CFBundleSignature</key>
<string>SDLX</string>
<key>CFBundleVersion</key>
<string>3.2.14</string>
<string>3.2.22</string>
</dict>
</plist>
+4 -4
View File
@@ -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.22.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.22;
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.22.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.22;
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "$(CONFIG_FRAMEWORK_LDFLAGS)";
PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL3;
+1 -1
View File
@@ -1,4 +1,4 @@
Title SDL 3.2.14
Title SDL 3.2.22
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)
+1 -1
View File
@@ -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
View File
@@ -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 = 22;
/*
// 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;
}
}
/**
+8 -3
View File
@@ -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
View 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
+1 -1
View File
@@ -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",
-21
View File
@@ -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
+8 -8
View File
@@ -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)
+2 -2
View File
@@ -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;
+1 -1
View 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)
+1 -1
View File
@@ -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.22
*
* It is almost always best to include just this one header instead of
* picking out individual headers included here. There are exceptions to
+2 -2
View File
@@ -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. */ \
+5 -2
View File
@@ -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.
+1 -1
View File
@@ -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;
/**
+14 -14
View File
@@ -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.
*
+2 -2
View File
@@ -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.
+5 -5
View File
@@ -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.
+3 -3
View File
@@ -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.
*
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+2 -1
View File
@@ -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;
+11 -11
View File
@@ -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
+3 -2
View File
@@ -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.
+1 -1
View File
@@ -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 22
/**
* This macro turns the version numbers into a numeric value.
+14 -1
View File
@@ -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:
*
+3 -3
View File
@@ -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
@@ -211,10 +211,7 @@ typedef unsigned int uintptr_t;
#if _MSC_VER >= 1400
#define HAVE__FSEEKI64 1
#endif
#endif /* _MSC_VER */
#else
#define HAVE_STDARG_H 1
#define HAVE_STDDEF_H 1
#endif /* _MSC_VER */
#endif
/* Enable various audio drivers */
+3 -3
View File
@@ -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);
+6
View File
@@ -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);
+40 -15
View File
@@ -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,7 +1413,13 @@ 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);
data->result[data->devs_seen++] = devid;
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 ? &current_audio.recording_device_count : &current_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,7 +1581,9 @@ int *SDL_GetAudioDeviceChannelMap(SDL_AudioDeviceID devid, int *count)
SDL_AudioDevice *device = ObtainPhysicalAudioDeviceDefaultAllowed(devid);
if (device) {
channels = device->spec.channels;
result = SDL_ChannelMapDup(device->chmap, channels);
if (channels > 0 && device->chmap) {
result = SDL_ChannelMapDup(device->chmap, channels);
}
}
ReleaseAudioDevice(device);
@@ -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;
+4
View File
@@ -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__)
+2 -2
View File
@@ -2114,8 +2114,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
+1 -1
View File
@@ -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
+2 -1
View File
@@ -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;
+1 -1
View File
@@ -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
{
+1 -1
View File
@@ -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);
+13 -8
View File
@@ -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
+1 -1
View File
@@ -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)
+2 -1
View File
@@ -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;
+1 -1
View File
@@ -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;
}
+1 -1
View File
@@ -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);
+19 -58
View File
@@ -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);
}
@@ -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();
}
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];
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);
}
(*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)
+1 -1
View File
@@ -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);
+7 -26
View File
@@ -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);
+13 -9
View File
@@ -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 = { &notification_client_vtbl, { 1 } };
static SDLMMNotificationClient notification_client = { &notification_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 *)&notification_client);
+1 -1
View File
@@ -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);
+72
View File
@@ -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)
{
+4 -4
View File
@@ -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,22,0
PRODUCTVERSION 3,2,22,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, 22, 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, 22, 0\0"
END
END
BLOCK "VarFileInfo"
+7
View File
@@ -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();
}
}
+4 -4
View File
@@ -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);
+7 -25
View 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);
status = SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST);
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;
+8 -4
View File
@@ -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
+4 -4
View File
@@ -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
+2 -2
View File
@@ -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;
}
+358 -46
View File
@@ -93,10 +93,10 @@
} \
}
#define CHECK_GRAPHICS_PIPELINE_BOUND \
if (!((CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER)->graphics_pipeline_bound) { \
SDL_assert_release(!"Graphics pipeline not bound!"); \
return; \
#define CHECK_GRAPHICS_PIPELINE_BOUND \
if (!((RenderPass *)render_pass)->graphics_pipeline) { \
SDL_assert_release(!"Graphics pipeline not bound!"); \
return; \
}
#define CHECK_COMPUTEPASS \
@@ -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;
commandBufferHeader->copy_pass.in_progress = false;
commandBufferHeader->swapchain_texture_acquired = false;
commandBufferHeader->submitted = false;
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,14 +1776,20 @@ SDL_GPURenderPass *SDL_BeginGPURenderPass(
depth_stencil_target_info);
commandBufferHeader = (CommandBufferCommonHeader *)command_buffer;
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;
}
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;
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;
}
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,15 +2265,22 @@ void SDL_EndGPURenderPass(
RENDERPASS_DEVICE->EndRenderPass(
RENDERPASS_COMMAND_BUFFER);
commandBufferCommonHeader = (CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER;
commandBufferCommonHeader->render_pass.in_progress = false;
for (Uint32 i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1)
{
commandBufferCommonHeader->render_pass.color_targets[i] = NULL;
if (RENDERPASS_DEVICE->debug_mode) {
commandBufferCommonHeader->render_pass.in_progress = false;
for (Uint32 i = 0; i < MAX_COLOR_TARGET_BINDINGS; i += 1)
{
commandBufferCommonHeader->render_pass.color_targets[i] = NULL;
}
commandBufferCommonHeader->render_pass.num_color_targets = 0;
commandBufferCommonHeader->render_pass.depth_stencil_target = NULL;
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);
}
commandBufferCommonHeader->render_pass.num_color_targets = 0;
commandBufferCommonHeader->render_pass.depth_stencil_target = NULL;
commandBufferCommonHeader->graphics_pipeline_bound = false;
}
// 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;
commandBufferHeader->compute_pass.in_progress = true;
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);
commandBufferCommonHeader = (CommandBufferCommonHeader *)COMPUTEPASS_COMMAND_BUFFER;
commandBufferCommonHeader->compute_pass.in_progress = false;
commandBufferCommonHeader->compute_pipeline_bound = false;
if (COMPUTEPASS_DEVICE->debug_mode) {
commandBufferCommonHeader = (CommandBufferCommonHeader *)COMPUTEPASS_COMMAND_BUFFER;
commandBufferCommonHeader->compute_pass.in_progress = 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;
commandBufferHeader->copy_pass.in_progress = true;
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);
((CommandBufferCommonHeader *)COPYPASS_COMMAND_BUFFER)->copy_pass.in_progress = false;
if (COPYPASS_DEVICE->debug_mode) {
((CommandBufferCommonHeader *)COPYPASS_COMMAND_BUFFER)->copy_pass.in_progress = false;
}
}
void SDL_GenerateMipmapsForGPUTexture(
+52 -3
View File
@@ -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:
+225 -155
View File
@@ -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,15 +4923,19 @@ static void D3D12_INTERNAL_WriteGPUDescriptors(
gpuBaseDescriptor->ptr = heap->descriptorHeapGPUStart.ptr + (heap->currentDescriptorIndex * heap->descriptorSize);
for (Uint32 i = 0; i < resourceHandleCount; i += 1) {
ID3D12Device_CopyDescriptorsSimple(
commandBuffer->renderer->device,
1,
gpuHeapCpuHandle,
resourceDescriptorHandles[i],
heapType);
// This will crash the driver if it gets a null handle! Cool!
if (resourceDescriptorHandles[i].ptr != 0)
{
ID3D12Device_CopyDescriptorsSimple(
commandBuffer->renderer->device,
1,
gpuHeapCpuHandle,
resourceDescriptorHandles[i],
heapType);
heap->currentDescriptorIndex += 1;
gpuHeapCpuHandle.ptr += heap->descriptorSize;
heap->currentDescriptorIndex += 1;
gpuHeapCpuHandle.ptr += heap->descriptorSize;
}
}
}
@@ -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_CHOICE,
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;
+63 -73
View File
@@ -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;
}
}
@@ -2412,14 +2401,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 +2639,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 +2651,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 +2662,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 +2688,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 +2700,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 +2711,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 +2743,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 +3122,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 +3130,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 +4559,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;
+167 -92
View File
@@ -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;
@@ -1265,13 +1278,20 @@ 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)); \
return ret; \
} 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)
#define SET_STRING_ERROR_AND_RETURN(msg, ret) SET_ERROR_AND_RETURN("%s", msg, ret)
@@ -5126,8 +5146,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 +5170,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 +5192,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 +5265,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 +5289,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 +5311,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 +6089,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 +6103,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 +6588,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 +6692,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 +6962,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 +7500,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 +7531,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 +7553,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 +7576,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 +7607,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 +7631,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;
}
}
@@ -8107,15 +8150,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 +8188,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 +8205,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 +8257,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 +8312,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 +8352,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 +8427,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 +8451,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 +8473,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 +8508,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 +8530,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 +8605,7 @@ static void VULKAN_INTERNAL_BindComputeDescriptorSets(
dynamicOffsetCount,
dynamicOffsets);
commandBuffer->needNewVertexUniformOffsets = false;
commandBuffer->needNewComputeUniformOffsets = false;
}
static void VULKAN_DispatchCompute(
@@ -8650,9 +8697,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 +9408,8 @@ static bool VULKAN_INTERNAL_AllocateCommandBuffer(
commandBuffer->usedUniformBuffers = SDL_malloc(
commandBuffer->usedUniformBufferCapacity * sizeof(VulkanUniformBuffer *));
commandBuffer->swapchainRequested = false;
// Pool it!
vulkanCommandPool->inactiveCommandBuffers[vulkanCommandPool->inactiveCommandBufferCount] = commandBuffer;
@@ -9518,26 +9570,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 +9941,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 +9966,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 +10017,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 +10402,7 @@ static void VULKAN_INTERNAL_CleanCommandBuffer(
commandBuffer->presentDataCount = 0;
commandBuffer->waitSemaphoreCount = 0;
commandBuffer->signalSemaphoreCount = 0;
commandBuffer->swapchainRequested = false;
// Reset defrag state
@@ -10435,11 +10500,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 +10566,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);
@@ -11647,7 +11719,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 +11727,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,9 +11756,10 @@ 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
@@ -11693,6 +11767,7 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
ASSIGN_DRIVER(VULKAN)
result->driverData = (SDL_GPURenderer *)renderer;
result->shader_formats = SDL_GPU_SHADERFORMAT_SPIRV;
/*
* Create initial swapchain array
+2 -3
View File
@@ -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.");
}
}
-4
View File
@@ -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.
+45 -19
View File
@@ -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;
@@ -918,6 +923,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 +969,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 +1191,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 +1610,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 +1627,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 +1776,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 +1807,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 +1837,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 +1930,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 +2118,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 +2139,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 +2162,10 @@ uint16_t get_usb_code_for_current_locale(void)
return 0x0;
}
#if defined(_MSC_VER)
#pragma warning (pop)
#endif
#ifdef __cplusplus
}
#endif
+1 -1
View File
@@ -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
}
+1
View File
@@ -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 */
};
+12 -4
View File
@@ -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);
+4 -2
View File
@@ -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,",
+33 -3
View File
@@ -1190,9 +1190,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 +2143,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 +2178,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);
}
}
+4
View File
@@ -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
+1 -1
View File
@@ -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)
+34 -1
View File
@@ -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) {
goodRead = GetHIDScaledCalibratedState(device, element, -32768, 32767, &value);
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
};
+40 -1
View File
@@ -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)
+52 -54
View File
@@ -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,69 +199,61 @@ 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
return;
}
#define READ_BUTTON(off, flag, button) \
SDL_SendJoystickButton( \
timestamp, \
joystick, \
button, \
#define READ_BUTTON(off, flag, button) \
SDL_SendJoystickButton( \
timestamp, \
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]; \
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]) \
ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = v; \
#define READ_AXIS(off, axis, invert) \
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]) \
ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = v; \
axis_value = (Sint16)HIDAPI_RemapVal(v, ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis], ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis], SDL_MIN_SINT16, SDL_MAX_SINT16); \
SDL_SendJoystickAxis( \
timestamp, \
joystick, \
SDL_SendJoystickAxis( \
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);
}
+2 -2
View File
@@ -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;
+14 -9
View File
@@ -812,14 +812,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;
@@ -1355,8 +1360,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 +1411,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;
+72 -44
View File
@@ -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,33 +948,46 @@ static bool LoadStickCalibration(SDL_DriverSwitch_Context *ctx)
readFactoryParams.unAddress = k_unSPIStickFactoryCalibrationStartOffset;
readFactoryParams.ucLength = k_unSPIStickFactoryCalibrationLength;
const int MAX_ATTEMPTS = 3;
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
break;
}
if (attempt == MAX_ATTEMPTS) {
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) {
userParamsReadSuccessCount += 1;
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) {
userParamsReadSuccessCount += 1;
pRightStickCal = user_reply->stickUserCalibration.rgucRightCalibration;
} else {
pRightStickCal = factory_reply->stickFactoryCalibration.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) {
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;
}
if (attempt == MAX_ATTEMPTS) {
return false;
}
}
}
// 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 > ctx->m_StickExtents[nStick].axis[nAxis].sMax) {
ctx->m_StickExtents[nStick].axis[nAxis].sMax = sRawValue;
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, 0, SDL_MIN_SINT16, 0);
}
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);
}
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 > ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax) {
ctx->m_SimpleStickExtents[nStick].axis[nAxis].sMax = sRawValue;
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, 0, SDL_MIN_SINT16, 0);
}
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);
}
static Uint8 RemapButton(SDL_DriverSwitch_Context *ctx, Uint8 button)
+8 -2
View File
@@ -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) {
+1
View File
@@ -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
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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;
}
+5 -7
View File
@@ -2685,6 +2685,8 @@ static void UpdateLogicalPresentation(SDL_Renderer *renderer)
view->pixel_h = (int) view->logical_dst_rect.h;
UpdatePixelViewport(renderer, view);
UpdatePixelClipRect(renderer, view);
QueueCmdSetViewport(renderer);
QueueCmdSetClipRect(renderer);
}
bool SDL_SetRenderLogicalPresentation(SDL_Renderer *renderer, int w, int h, SDL_RendererLogicalPresentation mode)
@@ -3304,10 +3306,6 @@ bool SDL_SetRenderDrawBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode)
return SDL_InvalidParamError("blendMode");
}
if (blendMode == SDL_BLENDMODE_INVALID) {
return SDL_InvalidParamError("blendMode");
}
if (!IsSupportedBlendMode(renderer, blendMode)) {
return SDL_Unsupported();
}
@@ -3605,7 +3603,7 @@ bool SDL_RenderLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count
#endif
SDL_RenderViewState *view = renderer->view;
const bool islogical = ((view == &renderer->main_view) && (view->logical_presentation_mode != SDL_LOGICAL_PRESENTATION_DISABLED));
const bool islogical = (view->logical_presentation_mode != SDL_LOGICAL_PRESENTATION_DISABLED);
if (islogical || (renderer->line_method == SDL_RENDERLINEMETHOD_GEOMETRY)) {
const float scale_x = view->current_scale.x;
@@ -3624,7 +3622,7 @@ bool SDL_RenderLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count
int num_indices = 0;
const int size_indices = 4;
int cur_index = -4;
const int is_looping = (points[0].x == points[count - 1].x && points[0].y == points[count - 1].y);
const bool is_looping = (points[0].x == points[count - 1].x && points[0].y == points[count - 1].y);
SDL_FPoint p; // previous point
p.x = p.y = 0.0f;
/* p q
@@ -3656,7 +3654,7 @@ bool SDL_RenderLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count
num_indices += 3;
// closed polyline, don´t draw twice the point
if (i || is_looping == 0) {
if (i || !is_looping) {
ADD_TRIANGLE(4, 5, 6)
ADD_TRIANGLE(4, 6, 7)
}
+16
View File
@@ -1651,6 +1651,8 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
} else {
renderdata->glGenTextures(1, &data->texture_v);
if (!GL_CheckError("glGenTexures()", renderer)) {
SDL_free(data->pixel_data);
SDL_free(data);
return false;
}
}
@@ -1665,6 +1667,8 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
} else {
renderdata->glGenTextures(1, &data->texture_u);
if (!GL_CheckError("glGenTexures()", renderer)) {
SDL_free(data->pixel_data);
SDL_free(data);
return false;
}
}
@@ -1672,11 +1676,15 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
renderdata->glBindTexture(data->texture_type, data->texture_u);
renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
if (!GL_CheckError("glTexImage2D()", renderer)) {
SDL_free(data->pixel_data);
SDL_free(data);
return false;
}
SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER, data->texture_u);
if (!SDL_GetYCbCRtoRGBConversionMatrix(texture->colorspace, texture->w, texture->h, 8)) {
SDL_free(data->pixel_data);
SDL_free(data);
return SDL_SetError("Unsupported YUV colorspace");
}
} else if (data->nv12) {
@@ -1686,6 +1694,8 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
} else {
renderdata->glGenTextures(1, &data->texture_u);
if (!GL_CheckError("glGenTexures()", renderer)) {
SDL_free(data->pixel_data);
SDL_free(data);
return false;
}
}
@@ -1693,11 +1703,15 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
renderdata->glBindTexture(data->texture_type, data->texture_u);
renderdata->glTexImage2D(data->texture_type, 0, GL_LUMINANCE_ALPHA, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
if (!GL_CheckError("glTexImage2D()", renderer)) {
SDL_free(data->pixel_data);
SDL_free(data);
return false;
}
SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER, data->texture_u);
if (!SDL_GetYCbCRtoRGBConversionMatrix(texture->colorspace, texture->w, texture->h, 8)) {
SDL_free(data->pixel_data);
SDL_free(data);
return SDL_SetError("Unsupported YUV colorspace");
}
}
@@ -1709,6 +1723,8 @@ static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
} else {
renderdata->glGenTextures(1, &data->texture);
if (!GL_CheckError("glGenTexures()", renderer)) {
SDL_free(data->pixel_data);
SDL_free(data);
return false;
}
}
+1 -1
View File
@@ -60,7 +60,7 @@ typedef struct
static int vsync_sema_id = 0;
// PRIVATE METHODS
static int vsync_handler(void)
static int vsync_handler(int reason)
{
iSignalSema(vsync_sema_id);
+2 -2
View File
@@ -3763,7 +3763,7 @@ static bool VULKAN_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand
VULKAN_SetupShaderConstants(renderer, cmd, texture, &constants);
switch (cmd->data.draw.texture_scale_mode) {
case VK_FILTER_NEAREST:
case SDL_SCALEMODE_NEAREST:
switch (cmd->data.draw.texture_address_mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
textureSampler = rendererData->samplers[VULKAN_SAMPLER_NEAREST_CLAMP];
@@ -3775,7 +3775,7 @@ static bool VULKAN_SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand
return SDL_SetError("Unknown texture address mode: %d", cmd->data.draw.texture_address_mode);
}
break;
case VK_FILTER_LINEAR:
case SDL_SCALEMODE_LINEAR:
switch (cmd->data.draw.texture_address_mode) {
case SDL_TEXTURE_ADDRESS_CLAMP:
textureSampler = rendererData->samplers[VULKAN_SAMPLER_LINEAR_CLAMP];
+6 -1
View File
@@ -41,7 +41,12 @@
#define environ (*_NSGetEnviron())
#elif defined(SDL_PLATFORM_FREEBSD)
#include <dlfcn.h>
#define environ ((char **)dlsym(RTLD_DEFAULT, "environ"))
static char **get_environ_rtld(void)
{
char ***environ_rtld = (char ***)dlsym(RTLD_DEFAULT, "environ");
return environ_rtld ? *environ_rtld : NULL;
}
#define environ (get_environ_rtld())
#else
extern char **environ;
#endif
+7
View File
@@ -1478,6 +1478,13 @@ DLMALLOC_EXPORT int mspace_mallopt(int, int);
#endif /* NO_MALLOC_STATS */
#ifndef LACKS_ERRNO_H
#include <errno.h> /* for MALLOC_FAILURE_ACTION */
#else /* LACKS_ERRNO_H */
#ifndef EINVAL
#define EINVAL 22
#endif
#ifndef ENOMEM
#define ENOMEM 12
#endif
#endif /* LACKS_ERRNO_H */
#ifdef DEBUG
#if ABORT_ON_ASSERT_FAILURE
+3
View File
@@ -34,6 +34,9 @@ static TitleStorageBootStrap *titlebootstrap[] = {
static UserStorageBootStrap *userbootstrap[] = {
#ifdef SDL_STORAGE_STEAM
&STEAM_userbootstrap,
#endif
#ifdef SDL_STORAGE_PRIVATE
&PRIVATE_userbootstrap,
#endif
&GENERIC_userbootstrap,
NULL
Loaded 100 of 152 files, more files were not shown because too many files have changed in this diff. Show more