From 012ff7bb161c19db4c8bf1f8df0bc81b41afda89 Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Wed, 2 Jul 2025 23:07:05 -0400 Subject: [PATCH] deps: update to SDL 3.2.16 (#3975) --- third-party/SDL/CMakeLists.txt | 2 +- .../SDL/Xcode/SDL/Info-Framework.plist | 4 +- .../Xcode/SDL/SDL.xcodeproj/project.pbxproj | 8 +- .../SDL/Xcode/SDL/pkg-support/SDL.info | 2 +- .../android-project/app/proguard-rules.pro | 2 + .../main/java/org/libsdl/app/SDLActivity.java | 41 +- third-party/SDL/docs/README-platforms.md | 2 +- third-party/SDL/include/SDL3/SDL.h | 2 +- third-party/SDL/include/SDL3/SDL_hints.h | 4 +- third-party/SDL/include/SDL3/SDL_init.h | 2 +- third-party/SDL/include/SDL3/SDL_pixels.h | 2 +- third-party/SDL/include/SDL3/SDL_stdinc.h | 4 +- third-party/SDL/include/SDL3/SDL_surface.h | 5 +- third-party/SDL/include/SDL3/SDL_version.h | 2 +- third-party/SDL/src/SDL_internal.h | 6 + third-party/SDL/src/audio/SDL_audio.c | 17 +- .../audio/emscripten/SDL_emscriptenaudio.c | 2 +- .../SDL/src/audio/pulseaudio/SDL_pulseaudio.c | 3 +- .../camera/emscripten/SDL_camera_emscripten.c | 2 +- .../SDL/src/core/android/SDL_android.c | 74 +--- third-party/SDL/src/core/windows/version.rc | 8 +- .../src/dialog/windows/SDL_windowsdialog.c | 8 +- third-party/SDL/src/events/SDL_events.c | 32 +- third-party/SDL/src/events/SDL_mouse.c | 12 +- third-party/SDL/src/gpu/SDL_gpu.c | 397 ++++++++++++++++-- third-party/SDL/src/gpu/SDL_sysgpu.h | 55 ++- third-party/SDL/src/gpu/d3d12/SDL_gpu_d3d12.c | 330 ++++++++------- third-party/SDL/src/gpu/metal/SDL_gpu_metal.m | 135 +++--- .../SDL/src/gpu/vulkan/SDL_gpu_vulkan.c | 184 ++++---- third-party/SDL/src/joystick/SDL_gamepad.c | 3 + third-party/SDL/src/joystick/SDL_joystick.c | 30 +- .../src/joystick/hidapi/SDL_hidapijoystick.c | 10 +- .../joystick/windows/SDL_rawinputjoystick.c | 2 +- .../SDL/src/render/ps2/SDL_render_ps2.c | 2 +- third-party/SDL/src/storage/SDL_storage.c | 3 + third-party/SDL/src/storage/SDL_sysstorage.h | 1 + third-party/SDL/src/tray/unix/SDL_tray.c | 2 +- third-party/SDL/src/video/SDL_sysvideo.h | 3 +- third-party/SDL/src/video/SDL_video.c | 13 +- .../SDL/src/video/cocoa/SDL_cocoaclipboard.m | 11 + .../SDL/src/video/cocoa/SDL_cocoamouse.m | 10 +- .../SDL/src/video/cocoa/SDL_cocoavideo.m | 4 - .../SDL/src/video/cocoa/SDL_cocoawindow.m | 17 + .../video/emscripten/SDL_emscriptenvideo.c | 2 +- .../SDL/src/video/kmsdrm/SDL_kmsdrmvideo.c | 13 +- third-party/SDL/src/video/psp/SDL_pspvideo.c | 2 + .../SDL/src/video/vita/SDL_vitavideo.c | 2 + .../SDL/src/video/vita/SDL_vitavideo.h | 2 - .../SDL/src/video/wayland/SDL_waylandevents.c | 30 +- .../src/video/wayland/SDL_waylandevents_c.h | 13 +- .../src/video/wayland/SDL_waylandkeyboard.c | 44 +- .../src/video/wayland/SDL_waylandkeyboard.h | 3 +- .../SDL/src/video/wayland/SDL_waylandvideo.c | 4 - .../SDL/src/video/windows/SDL_windowsvideo.c | 4 - third-party/SDL/src/video/x11/SDL_x11dyn.h | 3 + .../SDL/src/video/x11/SDL_x11keyboard.c | 4 +- third-party/SDL/src/video/x11/SDL_x11pen.c | 22 +- third-party/SDL/src/video/x11/SDL_x11video.c | 32 +- third-party/SDL/src/video/x11/SDL_x11window.c | 6 + vendor.yaml | 2 +- 60 files changed, 1071 insertions(+), 575 deletions(-) diff --git a/third-party/SDL/CMakeLists.txt b/third-party/SDL/CMakeLists.txt index 2b9c768847..1c120a5900 100644 --- a/third-party/SDL/CMakeLists.txt +++ b/third-party/SDL/CMakeLists.txt @@ -5,7 +5,7 @@ if(NOT DEFINED CMAKE_BUILD_TYPE) endif() # See docs/release_checklist.md -project(SDL3 LANGUAGES C VERSION "3.2.14") +project(SDL3 LANGUAGES C VERSION "3.2.16") if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) set(SDL3_MAINPROJECT ON) diff --git a/third-party/SDL/Xcode/SDL/Info-Framework.plist b/third-party/SDL/Xcode/SDL/Info-Framework.plist index 5c988e48b1..2f0338d685 100644 --- a/third-party/SDL/Xcode/SDL/Info-Framework.plist +++ b/third-party/SDL/Xcode/SDL/Info-Framework.plist @@ -19,10 +19,10 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 3.2.14 + 3.2.16 CFBundleSignature SDLX CFBundleVersion - 3.2.14 + 3.2.16 diff --git a/third-party/SDL/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/third-party/SDL/Xcode/SDL/SDL.xcodeproj/project.pbxproj index b5e5608c04..5a5d205290 100644 --- a/third-party/SDL/Xcode/SDL/SDL.xcodeproj/project.pbxproj +++ b/third-party/SDL/Xcode/SDL/SDL.xcodeproj/project.pbxproj @@ -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.16.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.16; 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.16.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.16; ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = "$(CONFIG_FRAMEWORK_LDFLAGS)"; PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL3; diff --git a/third-party/SDL/Xcode/SDL/pkg-support/SDL.info b/third-party/SDL/Xcode/SDL/pkg-support/SDL.info index 5edcd164df..6f42a55475 100644 --- a/third-party/SDL/Xcode/SDL/pkg-support/SDL.info +++ b/third-party/SDL/Xcode/SDL/pkg-support/SDL.info @@ -1,4 +1,4 @@ -Title SDL 3.2.14 +Title SDL 3.2.16 Version 1 Description SDL Library for macOS (http://www.libsdl.org) DefaultLocation /Library/Frameworks diff --git a/third-party/SDL/android-project/app/proguard-rules.pro b/third-party/SDL/android-project/app/proguard-rules.pro index 1eeb90e2c3..5f8ee6a25e 100644 --- a/third-party/SDL/android-project/app/proguard-rules.pro +++ b/third-party/SDL/android-project/app/proguard-rules.pro @@ -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 { diff --git a/third-party/SDL/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java b/third-party/SDL/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java index 33203d3d8a..361688d68e 100644 --- a/third-party/SDL/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/third-party/SDL/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java @@ -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 = 16; /* // 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; + } } /** diff --git a/third-party/SDL/docs/README-platforms.md b/third-party/SDL/docs/README-platforms.md index 77ae411d27..46a054a8ae 100644 --- a/third-party/SDL/docs/README-platforms.md +++ b/third-party/SDL/docs/README-platforms.md @@ -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) diff --git a/third-party/SDL/include/SDL3/SDL.h b/third-party/SDL/include/SDL3/SDL.h index a8eb7aeedf..ed1b32483a 100644 --- a/third-party/SDL/include/SDL3/SDL.h +++ b/third-party/SDL/include/SDL3/SDL.h @@ -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.16 * * It is almost always best to include just this one header instead of * picking out individual headers included here. There are exceptions to diff --git a/third-party/SDL/include/SDL3/SDL_hints.h b/third-party/SDL/include/SDL3/SDL_hints.h index 89fc545d43..a081535716 100644 --- a/third-party/SDL/include/SDL3/SDL_hints.h +++ b/third-party/SDL/include/SDL3/SDL_hints.h @@ -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. * diff --git a/third-party/SDL/include/SDL3/SDL_init.h b/third-party/SDL/include/SDL3/SDL_init.h index adf0de8a21..27ebe4b0ed 100644 --- a/third-party/SDL/include/SDL3/SDL_init.h +++ b/third-party/SDL/include/SDL3/SDL_init.h @@ -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 diff --git a/third-party/SDL/include/SDL3/SDL_pixels.h b/third-party/SDL/include/SDL3/SDL_pixels.h index 4127ac06c7..39596c1c98 100644 --- a/third-party/SDL/include/SDL3/SDL_pixels.h +++ b/third-party/SDL/include/SDL3/SDL_pixels.h @@ -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 diff --git a/third-party/SDL/include/SDL3/SDL_stdinc.h b/third-party/SDL/include/SDL3/SDL_stdinc.h index 8c547477ed..7df253fece 100644 --- a/third-party/SDL/include/SDL3/SDL_stdinc.h +++ b/third-party/SDL/include/SDL3/SDL_stdinc.h @@ -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. diff --git a/third-party/SDL/include/SDL3/SDL_surface.h b/third-party/SDL/include/SDL3/SDL_surface.h index be842fe38d..15fce042f7 100644 --- a/third-party/SDL/include/SDL3/SDL_surface.h +++ b/third-party/SDL/include/SDL3/SDL_surface.h @@ -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. diff --git a/third-party/SDL/include/SDL3/SDL_version.h b/third-party/SDL/include/SDL3/SDL_version.h index 2387fcff9c..435b3f95fe 100644 --- a/third-party/SDL/include/SDL3/SDL_version.h +++ b/third-party/SDL/include/SDL3/SDL_version.h @@ -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 16 /** * This macro turns the version numbers into a numeric value. diff --git a/third-party/SDL/src/SDL_internal.h b/third-party/SDL/src/SDL_internal.h index a345252f3a..8fcd96a7fa 100644 --- a/third-party/SDL/src/SDL_internal.h +++ b/third-party/SDL/src/SDL_internal.h @@ -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); diff --git a/third-party/SDL/src/audio/SDL_audio.c b/third-party/SDL/src/audio/SDL_audio.c index 5ddf97876c..fbe6e22a39 100644 --- a/third-party/SDL/src/audio/SDL_audio.c +++ b/third-party/SDL/src/audio/SDL_audio.c @@ -1743,13 +1743,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. diff --git a/third-party/SDL/src/audio/emscripten/SDL_emscriptenaudio.c b/third-party/SDL/src/audio/emscripten/SDL_emscriptenaudio.c index 55fb5b49fc..46b8b7645b 100644 --- a/third-party/SDL/src/audio/emscripten/SDL_emscriptenaudio.c +++ b/third-party/SDL/src/audio/emscripten/SDL_emscriptenaudio.c @@ -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); diff --git a/third-party/SDL/src/audio/pulseaudio/SDL_pulseaudio.c b/third-party/SDL/src/audio/pulseaudio/SDL_pulseaudio.c index 69e8c1a84c..4d618a6e2b 100644 --- a/third-party/SDL/src/audio/pulseaudio/SDL_pulseaudio.c +++ b/third-party/SDL/src/audio/pulseaudio/SDL_pulseaudio.c @@ -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; diff --git a/third-party/SDL/src/camera/emscripten/SDL_camera_emscripten.c b/third-party/SDL/src/camera/emscripten/SDL_camera_emscripten.c index fa2a51144e..36418c57ab 100644 --- a/third-party/SDL/src/camera/emscripten/SDL_camera_emscripten.c +++ b/third-party/SDL/src/camera/emscripten/SDL_camera_emscripten.c @@ -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); diff --git a/third-party/SDL/src/core/android/SDL_android.c b/third-party/SDL/src/core/android/SDL_android.c index eb450979a2..1cc9ccdb4e 100644 --- a/third-party/SDL/src/core/android/SDL_android.c +++ b/third-party/SDL/src/core/android/SDL_android.c @@ -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?"); } @@ -2585,65 +2588,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) diff --git a/third-party/SDL/src/core/windows/version.rc b/third-party/SDL/src/core/windows/version.rc index ad9e934453..3492918f5e 100644 --- a/third-party/SDL/src/core/windows/version.rc +++ b/third-party/SDL/src/core/windows/version.rc @@ -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,16,0 + PRODUCTVERSION 3,2,16,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, 16, 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, 16, 0\0" END END BLOCK "VarFileInfo" diff --git a/third-party/SDL/src/dialog/windows/SDL_windowsdialog.c b/third-party/SDL/src/dialog/windows/SDL_windowsdialog.c index 6822944fc0..364753cfdf 100644 --- a/third-party/SDL/src/dialog/windows/SDL_windowsdialog.c +++ b/third-party/SDL/src/dialog/windows/SDL_windowsdialog.c @@ -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); diff --git a/third-party/SDL/src/events/SDL_events.c b/third-party/SDL/src/events/SDL_events.c index eff205f71b..a151740524 100644 --- a/third-party/SDL/src/events/SDL_events.c +++ b/third-party/SDL/src/events/SDL_events.c @@ -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; diff --git a/third-party/SDL/src/events/SDL_mouse.c b/third-party/SDL/src/events/SDL_mouse.c index d84f5592ac..92f9913442 100644 --- a/third-party/SDL/src/events/SDL_mouse.c +++ b/third-party/SDL/src/events/SDL_mouse.c @@ -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 diff --git a/third-party/SDL/src/gpu/SDL_gpu.c b/third-party/SDL/src/gpu/SDL_gpu.c index 34c99f5f96..e1ad66c00b 100644 --- a/third-party/SDL/src/gpu/SDL_gpu.c +++ b/third-party/SDL/src/gpu/SDL_gpu.c @@ -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,29 @@ 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; + 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 +1702,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 +1750,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 +1763,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 +1775,18 @@ 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; + } } + return (SDL_GPURenderPass *)&(commandBufferHeader->render_pass); } @@ -1569,8 +1794,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 +1807,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 +1965,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 +1996,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 +2026,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 +2057,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 +2091,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 +2121,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 +2150,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 +2177,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 +2206,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 +2234,7 @@ void SDL_DrawGPUIndexedPrimitivesIndirect( if (RENDERPASS_DEVICE->debug_mode) { CHECK_RENDERPASS CHECK_GRAPHICS_PIPELINE_BOUND + SDL_GPU_CheckGraphicsBindings(render_pass); } RENDERPASS_DEVICE->DrawIndexedPrimitivesIndirect( @@ -1996,6 +2248,7 @@ void SDL_EndGPURenderPass( SDL_GPURenderPass *render_pass) { CommandBufferCommonHeader *commandBufferCommonHeader; + commandBufferCommonHeader = (CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER; if (render_pass == NULL) { SDL_InvalidParamError("render_pass"); @@ -2009,15 +2262,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 +2321,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 +2344,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 +2364,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 +2381,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 +2404,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 +2434,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 +2464,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 +2491,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 +2514,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 +2540,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 = false; + 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 +2607,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 +2862,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( diff --git a/third-party/SDL/src/gpu/SDL_sysgpu.h b/third-party/SDL/src/gpu/SDL_sysgpu.h index 3c2c786600..8469d9418b 100644 --- a/third-party/SDL/src/gpu/SDL_sysgpu.h +++ b/third-party/SDL/src/gpu/SDL_sysgpu.h @@ -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: diff --git a/third-party/SDL/src/gpu/d3d12/SDL_gpu_d3d12.c b/third-party/SDL/src/gpu/d3d12/SDL_gpu_d3d12.c index 737dbc300f..a92215910c 100644 --- a/third-party/SDL/src/gpu/d3d12/SDL_gpu_d3d12.c +++ b/third-party/SDL/src/gpu/d3d12/SDL_gpu_d3d12.c @@ -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; }; @@ -2886,12 +2885,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 +3171,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 +3349,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; @@ -4637,14 +4636,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 +4710,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 +4742,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 +4761,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 +4784,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 +4816,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 +4836,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 +4922,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 +4964,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 +4986,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 +5006,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 +5027,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 +5049,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 +5060,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 +5077,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 +5097,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 +5118,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 +5140,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 +5305,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 +5347,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 +5366,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 +5408,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 +5418,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 +5436,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 +5467,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 +5518,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 +5556,7 @@ static void D3D12_BindComputeStorageBuffers( buffer); d3d12CommandBuffer->computeReadOnlyStorageBuffers[firstSlot + i] = buffer; + d3d12CommandBuffer->computeReadOnlyStorageBufferDescriptorHandles[firstSlot + i] = buffer->srvDescriptor.cpuHandle; d3d12CommandBuffer->needComputeReadOnlyStorageBufferBind = true; } } @@ -5583,16 +5592,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 +5609,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 +5629,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 +5650,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 +5672,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 +5771,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 +7364,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); @@ -8819,6 +8833,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 +8847,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 +9180,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; diff --git a/third-party/SDL/src/gpu/metal/SDL_gpu_metal.m b/third-party/SDL/src/gpu/metal/SDL_gpu_metal.m index 0e3f6efa7e..7c2aefebb2 100644 --- a/third-party/SDL/src/gpu/metal/SDL_gpu_metal.m +++ b/third-party/SDL/src/gpu/metal/SDL_gpu_metal.m @@ -476,33 +476,21 @@ typedef struct MetalShader typedef struct MetalGraphicsPipeline { + GraphicsPipelineCommonHeader header; + id handle; SDL_GPURasterizerState rasterizerState; SDL_GPUPrimitiveType primitiveType; id 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 handle; - Uint32 numSamplers; - Uint32 numReadonlyStorageTextures; - Uint32 numReadWriteStorageTextures; - Uint32 numReadonlyStorageBuffers; - Uint32 numReadWriteStorageBuffers; - Uint32 numUniformBuffers; Uint32 threadcountX; Uint32 threadcountY; Uint32 threadcountZ; @@ -1059,12 +1047,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 +1195,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 +2400,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 +2638,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 +2650,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 +2661,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 +2687,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 +2699,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 +2710,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 +2742,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 +3121,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 +3129,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 +4558,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; diff --git a/third-party/SDL/src/gpu/vulkan/SDL_gpu_vulkan.c b/third-party/SDL/src/gpu/vulkan/SDL_gpu_vulkan.c index fc10ba7621..4467ef801b 100644 --- a/third-party/SDL/src/gpu/vulkan/SDL_gpu_vulkan.c +++ b/third-party/SDL/src/gpu/vulkan/SDL_gpu_vulkan.c @@ -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]; @@ -5126,8 +5138,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 +5162,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 +5184,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 +5257,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 +5281,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 +5303,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; @@ -6565,6 +6577,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 +6681,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; } @@ -7457,21 +7487,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 +7518,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 +7540,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 +7563,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 +7594,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 +7618,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 +8137,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 +8175,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 +8192,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 +8244,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 +8299,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 +8339,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 +8414,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 +8438,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 +8460,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 +8495,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 +8517,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; @@ -8650,9 +8684,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; @@ -9518,21 +9555,23 @@ 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); @@ -11693,6 +11732,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 diff --git a/third-party/SDL/src/joystick/SDL_gamepad.c b/third-party/SDL/src/joystick/SDL_gamepad.c index 86dd062769..385e890cf9 100644 --- a/third-party/SDL/src/joystick/SDL_gamepad.c +++ b/third-party/SDL/src/joystick/SDL_gamepad.c @@ -2754,6 +2754,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 +2763,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 +2773,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); diff --git a/third-party/SDL/src/joystick/SDL_joystick.c b/third-party/SDL/src/joystick/SDL_joystick.c index 7878b7cc68..921576854e 100644 --- a/third-party/SDL/src/joystick/SDL_joystick.c +++ b/third-party/SDL/src/joystick/SDL_joystick.c @@ -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; } } diff --git a/third-party/SDL/src/joystick/hidapi/SDL_hidapijoystick.c b/third-party/SDL/src/joystick/hidapi/SDL_hidapijoystick.c index 6293519ca6..c7607aeadf 100644 --- a/third-party/SDL/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/third-party/SDL/src/joystick/hidapi/SDL_hidapijoystick.c @@ -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) { diff --git a/third-party/SDL/src/joystick/windows/SDL_rawinputjoystick.c b/third-party/SDL/src/joystick/windows/SDL_rawinputjoystick.c index f37a1d81ce..8590d9a836 100644 --- a/third-party/SDL/src/joystick/windows/SDL_rawinputjoystick.c +++ b/third-party/SDL/src/joystick/windows/SDL_rawinputjoystick.c @@ -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; } diff --git a/third-party/SDL/src/render/ps2/SDL_render_ps2.c b/third-party/SDL/src/render/ps2/SDL_render_ps2.c index 713192c908..f414fbd0cd 100644 --- a/third-party/SDL/src/render/ps2/SDL_render_ps2.c +++ b/third-party/SDL/src/render/ps2/SDL_render_ps2.c @@ -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); diff --git a/third-party/SDL/src/storage/SDL_storage.c b/third-party/SDL/src/storage/SDL_storage.c index 75952ffd23..7c395b36a8 100644 --- a/third-party/SDL/src/storage/SDL_storage.c +++ b/third-party/SDL/src/storage/SDL_storage.c @@ -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 diff --git a/third-party/SDL/src/storage/SDL_sysstorage.h b/third-party/SDL/src/storage/SDL_sysstorage.h index 57d60d6474..f047e551f9 100644 --- a/third-party/SDL/src/storage/SDL_sysstorage.h +++ b/third-party/SDL/src/storage/SDL_sysstorage.h @@ -44,6 +44,7 @@ extern TitleStorageBootStrap GENERIC_titlebootstrap; // Steam does not have title storage APIs extern UserStorageBootStrap GENERIC_userbootstrap; +extern UserStorageBootStrap PRIVATE_userbootstrap; extern UserStorageBootStrap STEAM_userbootstrap; extern SDL_Storage *GENERIC_OpenFileStorage(const char *path); diff --git a/third-party/SDL/src/tray/unix/SDL_tray.c b/third-party/SDL/src/tray/unix/SDL_tray.c index 1c305a966c..e8a7b0d7ee 100644 --- a/third-party/SDL/src/tray/unix/SDL_tray.c +++ b/third-party/SDL/src/tray/unix/SDL_tray.c @@ -541,7 +541,7 @@ SDL_TrayMenu *SDL_CreateTraySubmenu(SDL_TrayEntry *entry) return NULL; } - entry->submenu->menu = (GtkMenuShell *)gtk_menu_new(); + entry->submenu->menu = g_object_ref_sink(gtk_menu_new()); entry->submenu->parent_tray = NULL; entry->submenu->parent_entry = entry; entry->submenu->nEntries = 0; diff --git a/third-party/SDL/src/video/SDL_sysvideo.h b/third-party/SDL/src/video/SDL_sysvideo.h index 6da8bd2e18..ad5bed288b 100644 --- a/third-party/SDL/src/video/SDL_sysvideo.h +++ b/third-party/SDL/src/video/SDL_sysvideo.h @@ -396,8 +396,7 @@ struct SDL_VideoDevice bool checked_texture_framebuffer; bool is_dummy; bool suspend_screensaver; - SDL_Window *wakeup_window; - SDL_Mutex *wakeup_lock; // Initialized only if WaitEventTimeout/SendWakeupEvent are supported + void *wakeup_window; int num_displays; SDL_VideoDisplay **displays; SDL_Rect desktop_bounds; diff --git a/third-party/SDL/src/video/SDL_video.c b/third-party/SDL/src/video/SDL_video.c index abeb2cb6b5..db38a19d0d 100644 --- a/third-party/SDL/src/video/SDL_video.c +++ b/third-party/SDL/src/video/SDL_video.c @@ -2513,7 +2513,9 @@ SDL_Window *SDL_CreateWindowWithProperties(SDL_PropertiesID props) SDL_UpdateWindowHierarchy(window, parent); if (_this->CreateSDLWindow && !_this->CreateSDLWindow(_this, window, props)) { + PUSH_SDL_ERROR() SDL_DestroyWindow(window); + POP_SDL_ERROR() return NULL; } @@ -2761,7 +2763,7 @@ SDL_Window *SDL_GetWindowFromID(SDL_WindowID id) } } } - SDL_SetError("Invalid window ID"); \ + SDL_SetError("Invalid window ID"); return NULL; } @@ -4279,9 +4281,7 @@ void SDL_DestroyWindow(SDL_Window *window) _this->current_glwin = NULL; } - if (_this->wakeup_window == window) { - _this->wakeup_window = NULL; - } + SDL_CompareAndSwapAtomicPointer(&_this->wakeup_window, window, NULL); // Now invalidate magic SDL_SetObjectValid(window, SDL_OBJECT_TYPE_WINDOW, false); @@ -5034,8 +5034,7 @@ bool SDL_GL_GetAttribute(SDL_GLAttr attr, int *value) } if (fbo_type != GL_NONE) { glGetFramebufferAttachmentParameterivFunc(GL_FRAMEBUFFER, attachment, attachmentattrib, (GLint *)value); - } - else { + } else { *value = 0; } if (glBindFramebufferFunc && (current_fbo != 0)) { @@ -5266,7 +5265,7 @@ bool SDL_GL_SwapWindow(SDL_Window *window) bool SDL_GL_DestroyContext(SDL_GLContext context) { if (!_this) { - return SDL_UninitializedVideo(); \ + return SDL_UninitializedVideo(); } if (!context) { return SDL_InvalidParamError("context"); diff --git a/third-party/SDL/src/video/cocoa/SDL_cocoaclipboard.m b/third-party/SDL/src/video/cocoa/SDL_cocoaclipboard.m index 42c2ad64ba..7039ff6ad5 100644 --- a/third-party/SDL/src/video/cocoa/SDL_cocoaclipboard.m +++ b/third-party/SDL/src/video/cocoa/SDL_cocoaclipboard.m @@ -158,6 +158,17 @@ bool Cocoa_SetClipboardData(SDL_VideoDevice *_this) @autoreleasepool { SDL_CocoaVideoData *data = (__bridge SDL_CocoaVideoData *)_this->internal; NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; + + // SetClipboardText specialization so text is available after the app quits + if (_this->clipboard_callback && _this->num_clipboard_mime_types == 1) { + if (SDL_strncmp(_this->clipboard_mime_types[0], "text/plain;charset=utf-8", 24) == 0) { + [pasteboard declareTypes:@[ NSPasteboardTypeString ] owner:nil]; + [pasteboard setString:@((char *)_this->clipboard_userdata) forType:NSPasteboardTypeString]; + data.clipboard_count = [pasteboard changeCount]; + return true; + } + } + NSPasteboardItem *newItem = [NSPasteboardItem new]; NSMutableArray *utiTypes = [NSMutableArray new]; Cocoa_PasteboardDataProvider *provider = [[Cocoa_PasteboardDataProvider alloc] initWith: _this->clipboard_callback userData: _this->clipboard_userdata]; diff --git a/third-party/SDL/src/video/cocoa/SDL_cocoamouse.m b/third-party/SDL/src/video/cocoa/SDL_cocoamouse.m index 530ca0c874..f8f582972f 100644 --- a/third-party/SDL/src/video/cocoa/SDL_cocoamouse.m +++ b/third-party/SDL/src/video/cocoa/SDL_cocoamouse.m @@ -450,12 +450,18 @@ void Cocoa_HandleMouseEvent(SDL_VideoDevice *_this, NSEvent *event) // All events except NSEventTypeMouseExited can only happen if the window // has mouse focus, so we'll always set the focus even if we happen to miss // NSEventTypeMouseEntered, which apparently happens if the window is - // created under the mouse on macOS 12.7 + // created under the mouse on macOS 12.7. But, only set the focus if + // the event acutally has a non-NULL window, otherwise what would happen + // is that after an NSEventTypeMouseEntered there would sometimes be + // NSEventTypeMouseMoved without a window causing us to suppress subsequent + // mouse move events. NSEventType event_type = [event type]; if (event_type == NSEventTypeMouseExited) { Cocoa_MouseFocus = NULL; } else { - Cocoa_MouseFocus = [event window]; + if ([event window] != NULL) { + Cocoa_MouseFocus = [event window]; + } } switch (event_type) { diff --git a/third-party/SDL/src/video/cocoa/SDL_cocoavideo.m b/third-party/SDL/src/video/cocoa/SDL_cocoavideo.m index 81baf7825f..aed193df44 100644 --- a/third-party/SDL/src/video/cocoa/SDL_cocoavideo.m +++ b/third-party/SDL/src/video/cocoa/SDL_cocoavideo.m @@ -49,9 +49,6 @@ static void Cocoa_VideoQuit(SDL_VideoDevice *_this); static void Cocoa_DeleteDevice(SDL_VideoDevice *device) { @autoreleasepool { - if (device->wakeup_lock) { - SDL_DestroyMutex(device->wakeup_lock); - } CFBridgingRelease(device->internal); SDL_free(device); } @@ -81,7 +78,6 @@ static SDL_VideoDevice *Cocoa_CreateDevice(void) return NULL; } device->internal = (SDL_VideoData *)CFBridgingRetain(data); - device->wakeup_lock = SDL_CreateMutex(); device->system_theme = Cocoa_GetSystemTheme(); // Set the function pointers diff --git a/third-party/SDL/src/video/cocoa/SDL_cocoawindow.m b/third-party/SDL/src/video/cocoa/SDL_cocoawindow.m index 3e9642a3c0..7be564af0f 100644 --- a/third-party/SDL/src/video/cocoa/SDL_cocoawindow.m +++ b/third-party/SDL/src/video/cocoa/SDL_cocoawindow.m @@ -2022,6 +2022,7 @@ static void Cocoa_SendMouseButtonClicks(SDL_Mouse *mouse, NSEvent *theEvent, SDL @interface SDL3View : NSView { SDL_Window *_sdlWindow; + NSTrackingArea *_trackingArea; // only used on macOS <= 11.0 } - (void)setSDLWindow:(SDL_Window *)window; @@ -2033,6 +2034,7 @@ static void Cocoa_SendMouseButtonClicks(SDL_Mouse *mouse, NSEvent *theEvent, SDL - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent; - (BOOL)wantsUpdateLayer; - (void)updateLayer; +- (void)updateTrackingAreas; @end @implementation SDL3View @@ -2113,6 +2115,21 @@ static void Cocoa_SendMouseButtonClicks(SDL_Mouse *mouse, NSEvent *theEvent, SDL } } +- (void)updateTrackingAreas +{ + [super updateTrackingAreas]; + + if (@available(macOS 12.0, *)) { + // we (currently) use the tracking areas as a workaround for older macOSes, but we might be safe everywhere... + } else { + SDL_CocoaWindowData *windata = (__bridge SDL_CocoaWindowData *)_sdlWindow->internal; + if (_trackingArea) { + [self removeTrackingArea:_trackingArea]; + } + _trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] options:NSTrackingMouseEnteredAndExited|NSTrackingActiveAlways owner:windata.listener userInfo:nil]; + [self addTrackingArea:_trackingArea]; + } +} @end static void Cocoa_UpdateMouseFocus() diff --git a/third-party/SDL/src/video/emscripten/SDL_emscriptenvideo.c b/third-party/SDL/src/video/emscripten/SDL_emscriptenvideo.c index 1496268610..e735ee8215 100644 --- a/third-party/SDL/src/video/emscripten/SDL_emscriptenvideo.c +++ b/third-party/SDL/src/video/emscripten/SDL_emscriptenvideo.c @@ -64,7 +64,7 @@ static SDL_SystemTheme Emscripten_GetSystemTheme(void) /* Technically, light theme can mean explicit light theme or no preference. https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme#syntax */ - int theme_code = EM_ASM_INT({ + int theme_code = MAIN_THREAD_EM_ASM_INT({ if (!window.matchMedia) { return -1; } diff --git a/third-party/SDL/src/video/kmsdrm/SDL_kmsdrmvideo.c b/third-party/SDL/src/video/kmsdrm/SDL_kmsdrmvideo.c index be1db82bd4..adca91c9fd 100644 --- a/third-party/SDL/src/video/kmsdrm/SDL_kmsdrmvideo.c +++ b/third-party/SDL/src/video/kmsdrm/SDL_kmsdrmvideo.c @@ -1368,9 +1368,14 @@ bool KMSDRM_CreateSurfaces(SDL_VideoDevice *_this, SDL_Window *window) windata->gs = KMSDRM_gbm_surface_create(viddata->gbm_dev, dispdata->mode.hdisplay, dispdata->mode.vdisplay, surface_fmt, surface_flags); - + if (!windata->gs && errno == ENOSYS) { + // Try again without the scanout flags, needed on NVIDIA drivers + windata->gs = KMSDRM_gbm_surface_create(viddata->gbm_dev, + dispdata->mode.hdisplay, dispdata->mode.vdisplay, + surface_fmt, 0); + } if (!windata->gs) { - return SDL_SetError("Could not create GBM surface"); + return SDL_SetError("Could not create GBM surface: %s", strerror(errno)); } /* We can't get the EGL context yet because SDL_CreateRenderer has not been called, @@ -1729,9 +1734,9 @@ bool KMSDRM_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propert } /* Create the window surfaces with the size we have just chosen. - Needs the window diverdata in place. */ + Needs the window driverdata in place. */ if (!KMSDRM_CreateSurfaces(_this, window)) { - return SDL_SetError("Can't window GBM/EGL surfaces on window creation."); + return false; } } // NON-Vulkan block ends. diff --git a/third-party/SDL/src/video/psp/SDL_pspvideo.c b/third-party/SDL/src/video/psp/SDL_pspvideo.c index 2458235ee2..afdb6bbae3 100644 --- a/third-party/SDL/src/video/psp/SDL_pspvideo.c +++ b/third-party/SDL/src/video/psp/SDL_pspvideo.c @@ -118,6 +118,8 @@ static SDL_VideoDevice *PSP_Create(void) device->PumpEvents = PSP_PumpEvents; + device->device_caps = VIDEO_DEVICE_CAPS_FULLSCREEN_ONLY; + return device; } diff --git a/third-party/SDL/src/video/vita/SDL_vitavideo.c b/third-party/SDL/src/video/vita/SDL_vitavideo.c index 6b5dbd78d0..3455dba300 100644 --- a/third-party/SDL/src/video/vita/SDL_vitavideo.c +++ b/third-party/SDL/src/video/vita/SDL_vitavideo.c @@ -153,6 +153,8 @@ static SDL_VideoDevice *VITA_Create(void) device->PumpEvents = VITA_PumpEvents; + device->device_caps = VIDEO_DEVICE_CAPS_FULLSCREEN_ONLY; + return device; } diff --git a/third-party/SDL/src/video/vita/SDL_vitavideo.h b/third-party/SDL/src/video/vita/SDL_vitavideo.h index 268bed84ae..f5b397b34d 100644 --- a/third-party/SDL/src/video/vita/SDL_vitavideo.h +++ b/third-party/SDL/src/video/vita/SDL_vitavideo.h @@ -60,8 +60,6 @@ extern SDL_Window *Vita_Window; // Display and window functions extern bool VITA_VideoInit(SDL_VideoDevice *_this); extern void VITA_VideoQuit(SDL_VideoDevice *_this); -extern bool VITA_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display); -extern bool VITA_SetDisplayMode(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_DisplayMode *mode); extern bool VITA_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props); extern void VITA_SetWindowTitle(SDL_VideoDevice *_this, SDL_Window *window); extern bool VITA_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/third-party/SDL/src/video/wayland/SDL_waylandevents.c b/third-party/SDL/src/video/wayland/SDL_waylandevents.c index ce32eb1aa9..291a467647 100644 --- a/third-party/SDL/src/video/wayland/SDL_waylandevents.c +++ b/third-party/SDL/src/video/wayland/SDL_waylandevents.c @@ -199,7 +199,6 @@ static Uint64 Wayland_EventTimestampMSToNS(Uint32 wl_timestamp_ms) timestamp_offset += SDL_MS_TO_NS(SDL_UINT64_C(0x100000000)); } last = wl_timestamp_ms; - wl_timestamp_ms += timestamp_offset; return SDL_MS_TO_NS(wl_timestamp_ms) + timestamp_offset; } @@ -213,11 +212,6 @@ static Uint64 Wayland_GetKeyboardTimestamp(struct SDL_WaylandInput *input, Uint3 return 0; } -static Uint64 Wayland_GetKeyboardTimestampRaw(struct SDL_WaylandInput *input, Uint32 wl_timestamp_ms) -{ - return input->keyboard_timestamp_ns ? input->keyboard_timestamp_ns : Wayland_EventTimestampMSToNS(wl_timestamp_ms); -} - static Uint64 Wayland_GetPointerTimestamp(struct SDL_WaylandInput *input, Uint32 wl_timestamp_ms) { if (wl_timestamp_ms) { @@ -273,10 +267,11 @@ void Wayland_CreateCursorShapeDevice(struct SDL_WaylandInput *input) static bool keyboard_repeat_handle(SDL_WaylandKeyboardRepeat *repeat_info, Uint64 elapsed) { bool ret = false; + while (elapsed >= repeat_info->next_repeat_ns) { if (repeat_info->scancode != SDL_SCANCODE_UNKNOWN) { - const Uint64 timestamp = repeat_info->wl_press_time_ns + repeat_info->next_repeat_ns; - SDL_SendKeyboardKeyIgnoreModifiers(Wayland_GetEventTimestamp(timestamp), repeat_info->keyboard_id, repeat_info->key, repeat_info->scancode, true); + const Uint64 timestamp = repeat_info->base_time_ns + repeat_info->next_repeat_ns; + SDL_SendKeyboardKeyIgnoreModifiers(timestamp, repeat_info->keyboard_id, repeat_info->key, repeat_info->scancode, true); } if (repeat_info->text[0]) { SDL_SendKeyboardText(repeat_info->text); @@ -295,8 +290,8 @@ static void keyboard_repeat_clear(SDL_WaylandKeyboardRepeat *repeat_info) repeat_info->is_key_down = false; } -static void keyboard_repeat_set(SDL_WaylandKeyboardRepeat *repeat_info, Uint32 keyboard_id, uint32_t key, Uint64 wl_press_time_ns, - uint32_t scancode, bool has_text, char text[8]) +static void keyboard_repeat_set(SDL_WaylandKeyboardRepeat *repeat_info, Uint32 keyboard_id, uint32_t key, Uint32 wl_press_time_ms, + Uint64 base_time_ns, uint32_t scancode, bool has_text, char text[8]) { if (!repeat_info->is_initialized || !repeat_info->repeat_rate) { return; @@ -304,12 +299,13 @@ static void keyboard_repeat_set(SDL_WaylandKeyboardRepeat *repeat_info, Uint32 k repeat_info->is_key_down = true; repeat_info->keyboard_id = keyboard_id; repeat_info->key = key; - repeat_info->wl_press_time_ns = wl_press_time_ns; + repeat_info->wl_press_time_ms = wl_press_time_ms; + repeat_info->base_time_ns = base_time_ns; repeat_info->sdl_press_time_ns = SDL_GetTicksNS(); repeat_info->next_repeat_ns = SDL_MS_TO_NS(repeat_info->repeat_delay_ms); repeat_info->scancode = scancode; if (has_text) { - SDL_copyp(repeat_info->text, text); + SDL_memcpy(repeat_info->text, text, sizeof(repeat_info->text)); } else { repeat_info->text[0] = '\0'; } @@ -1859,7 +1855,7 @@ static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard, char text[8]; bool has_text = false; bool handled_by_ime = false; - const Uint64 timestamp_raw_ns = Wayland_GetKeyboardTimestampRaw(input, time); + const Uint64 timestamp_ns = Wayland_GetKeyboardTimestamp(input, time); Wayland_UpdateImplicitGrabSerial(input, serial); @@ -1875,7 +1871,8 @@ static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard, * Using SDL_GetTicks would be wrong, as it would report when the release event is processed, * which may be off if the application hasn't pumped events for a while. */ - keyboard_repeat_handle(&input->keyboard_repeat, timestamp_raw_ns - input->keyboard_repeat.wl_press_time_ns); + const Uint64 elapsed = SDL_MS_TO_NS(time - input->keyboard_repeat.wl_press_time_ms); + keyboard_repeat_handle(&input->keyboard_repeat, elapsed); keyboard_repeat_clear(&input->keyboard_repeat); } keyboard_input_get_text(text, input, key, false, &handled_by_ime); @@ -1883,9 +1880,8 @@ static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard, const SDL_Scancode scancode = Wayland_GetScancodeForKey(input, key); Wayland_HandleModifierKeys(input, scancode, state == WL_KEYBOARD_KEY_STATE_PRESSED); - Uint64 timestamp = Wayland_GetKeyboardTimestamp(input, time); - SDL_SendKeyboardKeyIgnoreModifiers(timestamp, input->keyboard_id, key, scancode, state == WL_KEYBOARD_KEY_STATE_PRESSED); + SDL_SendKeyboardKeyIgnoreModifiers(timestamp_ns, input->keyboard_id, key, scancode, state == WL_KEYBOARD_KEY_STATE_PRESSED); if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { if (has_text && !(SDL_GetModState() & (SDL_KMOD_CTRL | SDL_KMOD_ALT))) { @@ -1894,7 +1890,7 @@ static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard, } } if (input->xkb.keymap && WAYLAND_xkb_keymap_key_repeats(input->xkb.keymap, key + 8)) { - keyboard_repeat_set(&input->keyboard_repeat, input->keyboard_id, key, timestamp_raw_ns, scancode, has_text, text); + keyboard_repeat_set(&input->keyboard_repeat, input->keyboard_id, key, time, timestamp_ns, scancode, has_text, text); } } } diff --git a/third-party/SDL/src/video/wayland/SDL_waylandevents_c.h b/third-party/SDL/src/video/wayland/SDL_waylandevents_c.h index 6158882ac5..d961b37ce5 100644 --- a/third-party/SDL/src/video/wayland/SDL_waylandevents_c.h +++ b/third-party/SDL/src/video/wayland/SDL_waylandevents_c.h @@ -49,17 +49,18 @@ typedef struct SDL_WaylandTabletInput typedef struct { - int32_t repeat_rate; // Repeat rate in range of [1, 1000] character(s) per second - int32_t repeat_delay_ms; // Time to first repeat event in milliseconds - Uint32 keyboard_id; // ID of the source keyboard. + Sint32 repeat_rate; // Repeat rate in range of [1, 1000] character(s) per second + Sint32 repeat_delay_ms; // Time to first repeat event in milliseconds + Uint32 keyboard_id; // ID of the source keyboard. bool is_initialized; bool is_key_down; - uint32_t key; - Uint64 wl_press_time_ns; // Key press time as reported by the Wayland API + Uint32 key; + Uint32 wl_press_time_ms; // Key press time as reported by the Wayland API in milliseconds + Uint64 base_time_ns; // Key press time as reported by the Wayland API in nanoseconds Uint64 sdl_press_time_ns; // Key press time expressed in SDL ticks Uint64 next_repeat_ns; // Next repeat event in nanoseconds - uint32_t scancode; + Uint32 scancode; char text[8]; } SDL_WaylandKeyboardRepeat; diff --git a/third-party/SDL/src/video/wayland/SDL_waylandkeyboard.c b/third-party/SDL/src/video/wayland/SDL_waylandkeyboard.c index df1628cd5b..6712f9d8c4 100644 --- a/third-party/SDL/src/video/wayland/SDL_waylandkeyboard.c +++ b/third-party/SDL/src/video/wayland/SDL_waylandkeyboard.c @@ -58,7 +58,7 @@ bool Wayland_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window, SDL_Prop if (internal->text_input_manager) { if (input && input->text_input) { - const SDL_Rect *rect = &input->text_input->cursor_rect; + const SDL_Rect *rect = &input->text_input->text_input_rect; enum zwp_text_input_v3_content_hint hint = ZWP_TEXT_INPUT_V3_CONTENT_HINT_NONE; enum zwp_text_input_v3_content_purpose purpose; @@ -125,12 +125,21 @@ bool Wayland_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window, SDL_Prop // Now that it's enabled, set the input properties zwp_text_input_v3_set_content_type(input->text_input->text_input, hint, purpose); if (!SDL_RectEmpty(rect)) { - // This gets reset on enable so we have to cache it + SDL_WindowData *wind = window->internal; + const SDL_Rect scaled_rect = { + (int)SDL_floor(window->text_input_rect.x / wind->pointer_scale.x), + (int)SDL_floor(window->text_input_rect.y / wind->pointer_scale.y), + (int)SDL_ceil(window->text_input_rect.w / wind->pointer_scale.x), + (int)SDL_ceil(window->text_input_rect.h / wind->pointer_scale.y) + }; + const int scaled_cursor = (int)SDL_floor(window->text_input_cursor / wind->pointer_scale.x); + + // Clamp the x value so it doesn't run too far past the end of the text input area. zwp_text_input_v3_set_cursor_rectangle(input->text_input->text_input, - rect->x, - rect->y, - rect->w, - rect->h); + SDL_min(scaled_rect.x + scaled_cursor, scaled_rect.x + scaled_rect.w), + scaled_rect.y, + 1, + scaled_rect.h); } zwp_text_input_v3_commit(input->text_input->text_input); } @@ -174,13 +183,24 @@ bool Wayland_UpdateTextInputArea(SDL_VideoDevice *_this, SDL_Window *window) if (internal->text_input_manager) { struct SDL_WaylandInput *input = internal->input; if (input && input->text_input) { - if (!SDL_RectsEqual(&window->text_input_rect, &input->text_input->cursor_rect)) { - SDL_copyp(&input->text_input->cursor_rect, &window->text_input_rect); + SDL_WindowData *wind = window->internal; + const SDL_Rect scaled_rect = { + (int)SDL_floor(window->text_input_rect.x / wind->pointer_scale.x), + (int)SDL_floor(window->text_input_rect.y / wind->pointer_scale.y), + (int)SDL_ceil(window->text_input_rect.w / wind->pointer_scale.x), + (int)SDL_ceil(window->text_input_rect.h / wind->pointer_scale.y) + }; + const int scaled_cursor = (int)SDL_floor(window->text_input_cursor / wind->pointer_scale.x); + if (!SDL_RectsEqual(&scaled_rect, &input->text_input->text_input_rect) || scaled_cursor != input->text_input->text_input_cursor) { + SDL_copyp(&input->text_input->text_input_rect, &scaled_rect); + input->text_input->text_input_cursor = scaled_cursor; + + // Clamp the x value so it doesn't run too far past the end of the text input area. zwp_text_input_v3_set_cursor_rectangle(input->text_input->text_input, - window->text_input_rect.x, - window->text_input_rect.y, - window->text_input_rect.w, - window->text_input_rect.h); + SDL_min(scaled_rect.x + scaled_cursor, scaled_rect.x + scaled_rect.w), + scaled_rect.y, + 1, + scaled_rect.h); zwp_text_input_v3_commit(input->text_input->text_input); } } diff --git a/third-party/SDL/src/video/wayland/SDL_waylandkeyboard.h b/third-party/SDL/src/video/wayland/SDL_waylandkeyboard.h index f570edb32f..a1ea076b7b 100644 --- a/third-party/SDL/src/video/wayland/SDL_waylandkeyboard.h +++ b/third-party/SDL/src/video/wayland/SDL_waylandkeyboard.h @@ -26,7 +26,8 @@ typedef struct SDL_WaylandTextInput { struct zwp_text_input_v3 *text_input; - SDL_Rect cursor_rect; + SDL_Rect text_input_rect; + int text_input_cursor; bool has_preedit; } SDL_WaylandTextInput; diff --git a/third-party/SDL/src/video/wayland/SDL_waylandvideo.c b/third-party/SDL/src/video/wayland/SDL_waylandvideo.c index 43019535f5..47971e6a30 100644 --- a/third-party/SDL/src/video/wayland/SDL_waylandvideo.c +++ b/third-party/SDL/src/video/wayland/SDL_waylandvideo.c @@ -446,9 +446,6 @@ static void Wayland_DeleteDevice(SDL_VideoDevice *device) WAYLAND_wl_display_disconnect(data->display); SDL_ClearProperty(SDL_GetGlobalProperties(), SDL_PROP_GLOBAL_VIDEO_WAYLAND_WL_DISPLAY_POINTER); } - if (device->wakeup_lock) { - SDL_DestroyMutex(device->wakeup_lock); - } SDL_free(data); SDL_free(device); SDL_WAYLAND_UnloadSymbols(); @@ -589,7 +586,6 @@ static SDL_VideoDevice *Wayland_CreateDevice(bool require_preferred_protocols) } device->internal = data; - device->wakeup_lock = SDL_CreateMutex(); // Set the function pointers device->VideoInit = Wayland_VideoInit; diff --git a/third-party/SDL/src/video/windows/SDL_windowsvideo.c b/third-party/SDL/src/video/windows/SDL_windowsvideo.c index 6103d52334..841a9ecba5 100644 --- a/third-party/SDL/src/video/windows/SDL_windowsvideo.c +++ b/third-party/SDL/src/video/windows/SDL_windowsvideo.c @@ -120,9 +120,6 @@ static void WIN_DeleteDevice(SDL_VideoDevice *device) SDL_UnloadObject(data->dxgiDLL); } #endif - if (device->wakeup_lock) { - SDL_DestroyMutex(device->wakeup_lock); - } SDL_free(device->internal->rawinput); SDL_free(device->internal); SDL_free(device); @@ -148,7 +145,6 @@ static SDL_VideoDevice *WIN_CreateDevice(void) return NULL; } device->internal = data; - device->wakeup_lock = SDL_CreateMutex(); device->system_theme = WIN_GetSystemTheme(); #if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) diff --git a/third-party/SDL/src/video/x11/SDL_x11dyn.h b/third-party/SDL/src/video/x11/SDL_x11dyn.h index e9831fcd60..7cd1e0eecb 100644 --- a/third-party/SDL/src/video/x11/SDL_x11dyn.h +++ b/third-party/SDL/src/video/x11/SDL_x11dyn.h @@ -71,6 +71,9 @@ #ifdef SDL_VIDEO_DRIVER_X11_XSHAPE #include #endif +#ifdef SDL_VIDEO_DRIVER_X11_XTEST +#include +#endif #ifdef __cplusplus extern "C" { diff --git a/third-party/SDL/src/video/x11/SDL_x11keyboard.c b/third-party/SDL/src/video/x11/SDL_x11keyboard.c index c48e82917f..2534092e41 100644 --- a/third-party/SDL/src/video/x11/SDL_x11keyboard.c +++ b/third-party/SDL/src/video/x11/SDL_x11keyboard.c @@ -762,7 +762,9 @@ void X11_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window, SDL_Prop break; } (void)SDL_snprintf(deeplink, sizeof(deeplink), - "steam://open/keyboard?XPosition=0&YPosition=0&Width=0&Height=0&Mode=%d", + "steam://open/keyboard?XPosition=%i&YPosition=%i&Width=%i&Height=%i&Mode=%d", + window->text_input_rect.x, window->text_input_rect.y, + window->text_input_rect.w, window->text_input_rect.h, mode); SDL_OpenURL(deeplink); videodata->steam_keyboard_open = true; diff --git a/third-party/SDL/src/video/x11/SDL_x11pen.c b/third-party/SDL/src/video/x11/SDL_x11pen.c index f16da51c5a..c29c629c4a 100644 --- a/third-party/SDL/src/video/x11/SDL_x11pen.c +++ b/third-party/SDL/src/video/x11/SDL_x11pen.c @@ -283,14 +283,16 @@ static X11_PenHandle *X11_MaybeAddPen(SDL_VideoDevice *_this, const XIDeviceInfo X11_PenHandle *X11_MaybeAddPenByDeviceID(SDL_VideoDevice *_this, int deviceid) { - SDL_VideoData *data = _this->internal; - int num_device_info = 0; - XIDeviceInfo *device_info = X11_XIQueryDevice(data->display, deviceid, &num_device_info); - if (device_info) { - SDL_assert(num_device_info == 1); - X11_PenHandle *handle = X11_MaybeAddPen(_this, device_info); - X11_XIFreeDeviceInfo(device_info); - return handle; + if (X11_Xinput2IsInitialized()) { + SDL_VideoData *data = _this->internal; + int num_device_info = 0; + XIDeviceInfo *device_info = X11_XIQueryDevice(data->display, deviceid, &num_device_info); + if (device_info) { + SDL_assert(num_device_info == 1); + X11_PenHandle *handle = X11_MaybeAddPen(_this, device_info); + X11_XIFreeDeviceInfo(device_info); + return handle; + } } return NULL; } @@ -306,6 +308,10 @@ void X11_RemovePenByDeviceID(int deviceid) void X11_InitPen(SDL_VideoDevice *_this) { + if (!X11_Xinput2IsInitialized()) { + return; // we need XIQueryDevice() for this. + } + SDL_VideoData *data = _this->internal; #define LOOKUP_PEN_ATOM(X) X11_XInternAtom(data->display, X, False) diff --git a/third-party/SDL/src/video/x11/SDL_x11video.c b/third-party/SDL/src/video/x11/SDL_x11video.c index c188f91f43..86f5b860ee 100644 --- a/third-party/SDL/src/video/x11/SDL_x11video.c +++ b/third-party/SDL/src/video/x11/SDL_x11video.c @@ -63,9 +63,6 @@ static void X11_DeleteDevice(SDL_VideoDevice *device) X11_XCloseDisplay(data->request_display); } SDL_free(data->windowlist); - if (device->wakeup_lock) { - SDL_DestroyMutex(device->wakeup_lock); - } SDL_free(device->internal); SDL_free(device); @@ -78,23 +75,6 @@ static bool X11_IsXWayland(Display *d) return X11_XQueryExtension(d, "XWAYLAND", &opcode, &event, &error) == True; } -static bool X11_CheckCurrentDesktop(const char *name) -{ - SDL_Environment *env = SDL_GetEnvironment(); - - const char *desktopVar = SDL_GetEnvironmentVariable(env, "DESKTOP_SESSION"); - if (desktopVar && SDL_strcasecmp(desktopVar, name) == 0) { - return true; - } - - desktopVar = SDL_GetEnvironmentVariable(env, "XDG_CURRENT_DESKTOP"); - if (desktopVar && SDL_strcasestr(desktopVar, name)) { - return true; - } - - return false; -} - static SDL_VideoDevice *X11_CreateDevice(void) { SDL_VideoDevice *device; @@ -146,8 +126,6 @@ static SDL_VideoDevice *X11_CreateDevice(void) return NULL; } - device->wakeup_lock = SDL_CreateMutex(); - #ifdef X11_DEBUG X11_XSynchronize(data->display, True); #endif @@ -275,17 +253,11 @@ static SDL_VideoDevice *X11_CreateDevice(void) device->device_caps = VIDEO_DEVICE_CAPS_HAS_POPUP_WINDOW_SUPPORT; - /* Openbox doesn't send the new window dimensions when entering fullscreen, so the events must be synthesized. - * This is otherwise not wanted, as it can break fullscreen window positioning on multi-monitor configurations. - */ - if (!X11_CheckCurrentDesktop("openbox")) { - device->device_caps |= VIDEO_DEVICE_CAPS_SENDS_FULLSCREEN_DIMENSIONS; - } - data->is_xwayland = X11_IsXWayland(x11_display); if (data->is_xwayland) { device->device_caps |= VIDEO_DEVICE_CAPS_MODE_SWITCHING_EMULATED | - VIDEO_DEVICE_CAPS_DISABLE_MOUSE_WARP_ON_FULLSCREEN_TRANSITIONS; + VIDEO_DEVICE_CAPS_DISABLE_MOUSE_WARP_ON_FULLSCREEN_TRANSITIONS | + VIDEO_DEVICE_CAPS_SENDS_FULLSCREEN_DIMENSIONS; } return device; diff --git a/third-party/SDL/src/video/x11/SDL_x11window.c b/third-party/SDL/src/video/x11/SDL_x11window.c index 7e15433499..3a6b4ae78d 100644 --- a/third-party/SDL/src/video/x11/SDL_x11window.c +++ b/third-party/SDL/src/video/x11/SDL_x11window.c @@ -1574,6 +1574,12 @@ void X11_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) X11_PumpEvents(_this); data->size_move_event_flags = 0; + /* A MapNotify or PropertyNotify may not have arrived, so ensure that the shown event is dispatched + * to apply pending state before clearing the flag. + */ + SDL_SendWindowEvent(window, SDL_EVENT_WINDOW_SHOWN, 0, 0); + data->was_shown = true; + // If a configure event was received (type is non-zero), send the final window size and coordinates. if (data->last_xconfigure.type) { int x, y; diff --git a/vendor.yaml b/vendor.yaml index 47f1bab810..ce69925abf 100644 --- a/vendor.yaml +++ b/vendor.yaml @@ -28,7 +28,7 @@ third-party/sqlite3: third-party/fmt: git: https://github.com/fmtlib/fmt/tree/11.1.4 third-party/SDL: - git: https://github.com/libsdl-org/SDL/tree/release-3.2.14 + git: https://github.com/libsdl-org/SDL/tree/release-3.2.16 third-party/imgui: git: https://github.com/ocornut/imgui/releases/tag/v1.91.8 third-party/tree-sitter: