diff --git a/cmake/sdlchecks.cmake b/cmake/sdlchecks.cmake index cbebf9ede2..06edce5bf5 100644 --- a/cmake/sdlchecks.cmake +++ b/cmake/sdlchecks.cmake @@ -826,7 +826,7 @@ endmacro() macro(CheckPTHREAD) cmake_push_check_state() if(SDL_PTHREADS) - if(ANDROID) + if(ANDROID OR SDL_PTHREADS_PRIVATE) # the android libc provides built-in support for pthreads, so no # additional linking or compile flags are necessary elseif(LINUX) diff --git a/include/SDL3/SDL_filesystem.h b/include/SDL3/SDL_filesystem.h index af3ca27e02..031feaf98e 100644 --- a/include/SDL3/SDL_filesystem.h +++ b/include/SDL3/SDL_filesystem.h @@ -444,10 +444,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetPathInfo(const char *path, SDL_PathInfo * Enumerate a directory tree, filtered by pattern, and return a list. * * Files are filtered out if they don't match the string in `pattern`, which - * may contain wildcard characters '\*' (match everything) and '?' (match one + * may contain wildcard characters `*` (match everything) and `?` (match one * character). If pattern is NULL, no filtering is done and all results are * returned. Subdirectories are permitted, and are specified with a path - * separator of '/'. Wildcard characters '\*' and '?' never match a path + * separator of `/`. Wildcard characters `*` and `?` never match a path * separator. * * `flags` may be set to SDL_GLOB_CASEINSENSITIVE to make the pattern matching diff --git a/include/SDL3/SDL_mouse.h b/include/SDL3/SDL_mouse.h index 911636b9b4..4ecd1d0010 100644 --- a/include/SDL3/SDL_mouse.h +++ b/include/SDL3/SDL_mouse.h @@ -578,15 +578,16 @@ extern SDL_DECLSPEC SDL_Cursor * SDLCALL SDL_CreateCursor(const Uint8 *data, /** * Create a color cursor. * - * If this function is passed a surface with alternate representations, the - * surface will be interpreted as the content to be used for 100% display - * scale, and the alternate representations will be used for high DPI - * situations. For example, if the original surface is 32x32, then on a 2x - * macOS display or 200% display scale on Windows, a 64x64 version of the - * image will be used, if available. If a matching version of the image isn't - * available, the closest larger size image will be downscaled to the - * appropriate size and be used instead, if available. Otherwise, the closest - * smaller image will be upscaled and be used instead. + * If this function is passed a surface with alternate representations added + * with SDL_AddSurfaceAlternateImage(), the surface will be interpreted as the + * content to be used for 100% display scale, and the alternate + * representations will be used for high DPI situations. For example, if the + * original surface is 32x32, then on a 2x macOS display or 200% display scale + * on Windows, a 64x64 version of the image will be used, if available. If a + * matching version of the image isn't available, the closest larger size + * image will be downscaled to the appropriate size and be used instead, if + * available. Otherwise, the closest smaller image will be upscaled and be + * used instead. * * \param surface an SDL_Surface structure representing the cursor image. * \param hot_x the x position of the cursor hot spot. @@ -598,6 +599,7 @@ extern SDL_DECLSPEC SDL_Cursor * SDLCALL SDL_CreateCursor(const Uint8 *data, * * \since This function is available since SDL 3.2.0. * + * \sa SDL_AddSurfaceAlternateImage * \sa SDL_CreateCursor * \sa SDL_CreateSystemCursor * \sa SDL_DestroyCursor diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index e56a6ae10e..79b603a18c 100644 --- a/include/SDL3/SDL_video.h +++ b/include/SDL3/SDL_video.h @@ -1680,15 +1680,16 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetWindowTitle(SDL_Window *window); /** * Set the icon for a window. * - * If this function is passed a surface with alternate representations, the - * surface will be interpreted as the content to be used for 100% display - * scale, and the alternate representations will be used for high DPI - * situations. For example, if the original surface is 32x32, then on a 2x - * macOS display or 200% display scale on Windows, a 64x64 version of the - * image will be used, if available. If a matching version of the image isn't - * available, the closest larger size image will be downscaled to the - * appropriate size and be used instead, if available. Otherwise, the closest - * smaller image will be upscaled and be used instead. + * If this function is passed a surface with alternate representations added + * using SDL_AddSurfaceAlternateImage(), the surface will be interpreted as + * the content to be used for 100% display scale, and the alternate + * representations will be used for high DPI situations. For example, if the + * original surface is 32x32, then on a 2x macOS display or 200% display scale + * on Windows, a 64x64 version of the image will be used, if available. If a + * matching version of the image isn't available, the closest larger size + * image will be downscaled to the appropriate size and be used instead, if + * available. Otherwise, the closest smaller image will be upscaled and be + * used instead. * * \param window the window to change. * \param icon an SDL_Surface structure containing the icon for the window. @@ -1698,6 +1699,8 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetWindowTitle(SDL_Window *window); * \threadsafety This function should only be called on the main thread. * * \since This function is available since SDL 3.2.0. + * + * \sa SDL_AddSurfaceAlternateImage */ extern SDL_DECLSPEC bool SDLCALL SDL_SetWindowIcon(SDL_Window *window, SDL_Surface *icon); diff --git a/include/build_config/SDL_build_config.h.cmake b/include/build_config/SDL_build_config.h.cmake index f58d43ea1c..ab5ce710a2 100644 --- a/include/build_config/SDL_build_config.h.cmake +++ b/include/build_config/SDL_build_config.h.cmake @@ -33,6 +33,10 @@ #cmakedefine SDL_PLATFORM_PRIVATE 1 +#ifdef SDL_PLATFORM_PRIVATE +#include "SDL_begin_config_private.h" +#endif + #cmakedefine HAVE_GCC_ATOMICS 1 #cmakedefine HAVE_GCC_SYNC_LOCK_TEST_AND_SET 1 @@ -369,6 +373,8 @@ #cmakedefine SDL_TIME_N3DS 1 #cmakedefine SDL_TIME_NGAGE 1 +#cmakedefine SDL_TIME_PRIVATE 1 + /* Enable various timer systems */ #cmakedefine SDL_TIMER_HAIKU 1 #cmakedefine SDL_TIMER_UNIX 1 @@ -473,6 +479,8 @@ #cmakedefine SDL_GPU_VULKAN 1 #cmakedefine SDL_GPU_METAL 1 +#cmakedefine SDL_GPU_PRIVATE 1 + /* Enable system power support */ #cmakedefine SDL_POWER_ANDROID 1 #cmakedefine SDL_POWER_LINUX 1 @@ -507,6 +515,8 @@ /* Enable system storage support */ #cmakedefine SDL_STORAGE_STEAM @SDL_STORAGE_STEAM@ +#cmakedefine SDL_STORAGE_PRIVATE 1 + /* Enable system FSops support */ #cmakedefine SDL_FSOPS_POSIX 1 #cmakedefine SDL_FSOPS_WINDOWS 1 diff --git a/src/camera/emscripten/SDL_camera_emscripten.c b/src/camera/emscripten/SDL_camera_emscripten.c index fa2a51144e..36418c57ab 100644 --- a/src/camera/emscripten/SDL_camera_emscripten.c +++ b/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/src/core/gdk/SDL_gdk.cpp b/src/core/gdk/SDL_gdk.cpp index 738daa5b78..4e792ef270 100644 --- a/src/core/gdk/SDL_gdk.cpp +++ b/src/core/gdk/SDL_gdk.cpp @@ -105,7 +105,7 @@ bool GDK_RegisterChangeNotifications(void) SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "[GDK] in RegisterAppConstrainedChangeNotification handler"); SDL_VideoDevice *_this = SDL_GetVideoDevice(); if (_this) { - if (constrained) { + if (constrained && !((_this->windows) && _this->windows->text_input_active)) { SDL_SetKeyboardFocus(NULL); } else { SDL_SetKeyboardFocus(_this->windows); diff --git a/src/events/SDL_keymap.c b/src/events/SDL_keymap.c index 32e4975e7d..318fc6864b 100644 --- a/src/events/SDL_keymap.c +++ b/src/events/SDL_keymap.c @@ -97,16 +97,74 @@ void SDL_SetKeymapEntry(SDL_Keymap *keymap, SDL_Scancode scancode, SDL_Keymod mo SDL_Keycode SDL_GetKeymapKeycode(SDL_Keymap *keymap, SDL_Scancode scancode, SDL_Keymod modstate) { - SDL_Keycode keycode; + if (keymap) { + const void *value; + const SDL_Keymod normalized_modstate = NormalizeModifierStateForKeymap(modstate); + Uint32 key = ((Uint32)normalized_modstate << 16) | scancode; - const Uint32 key = ((Uint32)NormalizeModifierStateForKeymap(modstate) << 16) | scancode; - const void *value; - if (keymap && SDL_FindInHashTable(keymap->scancode_to_keycode, (void *)(uintptr_t)key, &value)) { - keycode = (SDL_Keycode)(uintptr_t)value; - } else { - keycode = SDL_GetDefaultKeyFromScancode(scancode, modstate); + // First, try the requested set of modifiers. + if (SDL_FindInHashTable(keymap->scancode_to_keycode, (void *)(uintptr_t)key, &value)) { + return (SDL_Keycode)(uintptr_t)value; + } + + // If the requested set of modifiers was not found, search for the key from the highest to lowest modifier levels. + if (normalized_modstate) { + SDL_Keymod caps_mask = normalized_modstate & SDL_KMOD_CAPS; + + for (int i = caps_mask ? 2 : 1; i; --i) { + // Shift level 5 + if (normalized_modstate & SDL_KMOD_LEVEL5) { + const SDL_Keymod shifted_modstate = SDL_KMOD_LEVEL5 | caps_mask; + key = ((Uint32)shifted_modstate << 16) | scancode; + + if (shifted_modstate != normalized_modstate && SDL_FindInHashTable(keymap->scancode_to_keycode, (void *)(uintptr_t)key, &value)) { + return (SDL_Keycode)(uintptr_t)value; + } + } + + // Shift level 4 (Level 3 + Shift) + if ((normalized_modstate & (SDL_KMOD_MODE | SDL_KMOD_SHIFT)) == (SDL_KMOD_MODE | SDL_KMOD_SHIFT)) { + const SDL_Keymod shifted_modstate = SDL_KMOD_MODE | SDL_KMOD_SHIFT | caps_mask; + key = ((Uint32)shifted_modstate << 16) | scancode; + + if (shifted_modstate != normalized_modstate && SDL_FindInHashTable(keymap->scancode_to_keycode, (void *)(uintptr_t)key, &value)) { + return (SDL_Keycode)(uintptr_t)value; + } + } + + // Shift level 3 + if (normalized_modstate & SDL_KMOD_MODE) { + const SDL_Keymod shifted_modstate = SDL_KMOD_MODE | caps_mask; + key = ((Uint32)shifted_modstate << 16) | scancode; + + if (shifted_modstate != normalized_modstate && SDL_FindInHashTable(keymap->scancode_to_keycode, (void *)(uintptr_t)key, &value)) { + return (SDL_Keycode)(uintptr_t)value; + } + } + + // Shift level 2 + if (normalized_modstate & SDL_KMOD_SHIFT) { + const SDL_Keymod shifted_modstate = SDL_KMOD_SHIFT | caps_mask; + key = ((Uint32)shifted_modstate << 16) | scancode; + + if (shifted_modstate != normalized_modstate && SDL_FindInHashTable(keymap->scancode_to_keycode, (void *)(uintptr_t)key, &value)) { + return (SDL_Keycode)(uintptr_t)value; + } + } + + // Shift Level 1 (unmodified) + key = ((Uint32)caps_mask << 16) | scancode; + if (SDL_FindInHashTable(keymap->scancode_to_keycode, (void *)(uintptr_t)key, &value)) { + return (SDL_Keycode)(uintptr_t)value; + } + + // Clear the capslock mask, if set. + caps_mask = SDL_KMOD_NONE; + } + } } - return keycode; + + return SDL_GetDefaultKeyFromScancode(scancode, modstate); } SDL_Scancode SDL_GetKeymapScancode(SDL_Keymap *keymap, SDL_Keycode keycode, SDL_Keymod *modstate) diff --git a/src/gpu/SDL_gpu.c b/src/gpu/SDL_gpu.c index 3008cc24cb..1db3111dc8 100644 --- a/src/gpu/SDL_gpu.c +++ b/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,12 +174,18 @@ #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 @@ -511,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 @@ -1482,15 +1555,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; } @@ -1681,14 +1768,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); } @@ -1696,8 +1787,6 @@ void SDL_BindGPUGraphicsPipeline( SDL_GPURenderPass *render_pass, SDL_GPUGraphicsPipeline *graphics_pipeline) { - CommandBufferCommonHeader *commandBufferHeader; - if (render_pass == NULL) { SDL_InvalidParamError("render_pass"); return; @@ -1711,8 +1800,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( @@ -1867,6 +1958,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( @@ -1894,6 +1989,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( @@ -1920,6 +2019,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( @@ -1947,10 +2050,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( @@ -1978,6 +2084,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( @@ -2004,6 +2114,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( @@ -2029,6 +2143,7 @@ void SDL_DrawGPUIndexedPrimitives( if (RENDERPASS_DEVICE->debug_mode) { CHECK_RENDERPASS CHECK_GRAPHICS_PIPELINE_BOUND + SDL_GPU_CheckGraphicsBindings(render_pass); } RENDERPASS_DEVICE->DrawIndexedPrimitives( @@ -2055,6 +2170,7 @@ void SDL_DrawGPUPrimitives( if (RENDERPASS_DEVICE->debug_mode) { CHECK_RENDERPASS CHECK_GRAPHICS_PIPELINE_BOUND + SDL_GPU_CheckGraphicsBindings(render_pass); } RENDERPASS_DEVICE->DrawPrimitives( @@ -2083,6 +2199,7 @@ void SDL_DrawGPUPrimitivesIndirect( if (RENDERPASS_DEVICE->debug_mode) { CHECK_RENDERPASS CHECK_GRAPHICS_PIPELINE_BOUND + SDL_GPU_CheckGraphicsBindings(render_pass); } RENDERPASS_DEVICE->DrawPrimitivesIndirect( @@ -2110,6 +2227,7 @@ void SDL_DrawGPUIndexedPrimitivesIndirect( if (RENDERPASS_DEVICE->debug_mode) { CHECK_RENDERPASS CHECK_GRAPHICS_PIPELINE_BOUND + SDL_GPU_CheckGraphicsBindings(render_pass); } RENDERPASS_DEVICE->DrawIndexedPrimitivesIndirect( @@ -2123,6 +2241,7 @@ void SDL_EndGPURenderPass( SDL_GPURenderPass *render_pass) { CommandBufferCommonHeader *commandBufferCommonHeader; + commandBufferCommonHeader = (CommandBufferCommonHeader *)RENDERPASS_COMMAND_BUFFER; if (render_pass == NULL) { SDL_InvalidParamError("render_pass"); @@ -2136,15 +2255,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 @@ -2211,7 +2337,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); } @@ -2219,8 +2357,6 @@ void SDL_BindGPUComputePipeline( SDL_GPUComputePass *compute_pass, SDL_GPUComputePipeline *compute_pipeline) { - CommandBufferCommonHeader *commandBufferHeader; - if (compute_pass == NULL) { SDL_InvalidParamError("compute_pass"); return; @@ -2238,8 +2374,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( @@ -2259,6 +2397,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( @@ -2285,6 +2427,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( @@ -2311,6 +2457,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( @@ -2334,6 +2484,7 @@ void SDL_DispatchGPUCompute( if (COMPUTEPASS_DEVICE->debug_mode) { CHECK_COMPUTEPASS CHECK_COMPUTE_PIPELINE_BOUND + SDL_GPU_CheckComputeBindings(compute_pass); } COMPUTEPASS_DEVICE->DispatchCompute( @@ -2356,6 +2507,7 @@ void SDL_DispatchGPUComputeIndirect( if (COMPUTEPASS_DEVICE->debug_mode) { CHECK_COMPUTEPASS CHECK_COMPUTE_PIPELINE_BOUND + SDL_GPU_CheckComputeBindings(compute_pass); } COMPUTEPASS_DEVICE->DispatchComputeIndirect( @@ -2381,9 +2533,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 @@ -2441,7 +2600,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); } @@ -2699,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/src/gpu/SDL_sysgpu.h b/src/gpu/SDL_sysgpu.h index ee7fd10f2f..b4b54b2693 100644 --- a/src/gpu/SDL_sysgpu.h +++ b/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 diff --git a/src/gpu/d3d12/SDL_gpu_d3d12.c b/src/gpu/d3d12/SDL_gpu_d3d12.c index db803f5df0..618e6d2ba5 100644 --- a/src/gpu/d3d12/SDL_gpu_d3d12.c +++ b/src/gpu/d3d12/SDL_gpu_d3d12.c @@ -1004,26 +1004,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 @@ -1087,22 +1099,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; }; @@ -1121,16 +1125,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; }; @@ -2884,12 +2883,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)) { @@ -3170,15 +3169,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); @@ -4633,14 +4632,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); @@ -4707,21 +4706,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; } } @@ -4739,10 +4738,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; } } @@ -4758,12 +4757,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; } } @@ -4781,21 +4780,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; } } @@ -4813,10 +4812,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; } } @@ -4833,12 +4832,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; } } @@ -4919,15 +4918,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; + } } } @@ -4962,16 +4965,16 @@ static void D3D12_INTERNAL_BindGraphicsResources( } 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( @@ -4979,15 +4982,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( @@ -4999,16 +5002,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( @@ -5020,16 +5023,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( @@ -5042,7 +5045,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], @@ -5053,16 +5056,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( @@ -5070,15 +5073,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( @@ -5090,16 +5093,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( @@ -5111,16 +5114,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( @@ -5133,7 +5136,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], @@ -5298,15 +5301,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 @@ -5340,6 +5343,7 @@ static void D3D12_BeginComputePass( D3D12_RESOURCE_STATE_UNORDERED_ACCESS); d3d12CommandBuffer->computeReadWriteStorageTextureSubresources[i] = subresource; + d3d12CommandBuffer->computeReadWriteStorageTextureDescriptorHandles[i] = subresource->uavHandle.cpuHandle; D3D12_INTERNAL_TrackTexture( d3d12CommandBuffer, @@ -5358,6 +5362,7 @@ static void D3D12_BeginComputePass( D3D12_RESOURCE_STATE_UNORDERED_ACCESS); d3d12CommandBuffer->computeReadWriteStorageBuffers[i] = buffer; + d3d12CommandBuffer->computeReadWriteStorageBufferDescriptorHandles[i] = buffer->uavDescriptor.cpuHandle; D3D12_INTERNAL_TrackBuffer( d3d12CommandBuffer, @@ -5399,7 +5404,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); @@ -5409,9 +5414,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( @@ -5427,9 +5432,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( @@ -5458,21 +5463,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; } } @@ -5509,6 +5514,7 @@ static void D3D12_BindComputeStorageTextures( container->activeTexture); d3d12CommandBuffer->computeReadOnlyStorageTextures[firstSlot + i] = container->activeTexture; + d3d12CommandBuffer->computeReadOnlyStorageTextureDescriptorHandles[firstSlot + i] = container->activeTexture->srvHandle.cpuHandle; d3d12CommandBuffer->needComputeReadOnlyStorageTextureBind = true; } } @@ -5546,6 +5552,7 @@ static void D3D12_BindComputeStorageBuffers( buffer); d3d12CommandBuffer->computeReadOnlyStorageBuffers[firstSlot + i] = buffer; + d3d12CommandBuffer->computeReadOnlyStorageBufferDescriptorHandles[firstSlot + i] = buffer->srvDescriptor.cpuHandle; d3d12CommandBuffer->needComputeReadOnlyStorageBufferBind = true; } } @@ -5581,16 +5588,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( @@ -5598,15 +5605,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( @@ -5618,16 +5625,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( @@ -5639,16 +5646,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( @@ -5661,7 +5668,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], @@ -5760,8 +5767,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; } @@ -7351,20 +7361,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); diff --git a/src/gpu/metal/SDL_gpu_metal.m b/src/gpu/metal/SDL_gpu_metal.m index cd1d90acd2..26dea45462 100644 --- a/src/gpu/metal/SDL_gpu_metal.m +++ b/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; @@ -1085,12 +1073,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; @@ -1234,14 +1222,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; } } @@ -2439,14 +2427,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); @@ -2677,11 +2665,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; } @@ -2689,10 +2677,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; } @@ -2700,20 +2688,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 @@ -2726,11 +2714,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; } @@ -2738,10 +2726,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; } @@ -2749,20 +2737,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 @@ -2781,38 +2769,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 @@ -3160,7 +3148,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); @@ -3168,22 +3156,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)]; } } } diff --git a/src/gpu/vulkan/SDL_gpu_vulkan.c b/src/gpu/vulkan/SDL_gpu_vulkan.c index 9ed7ecad16..5109928381 100644 --- a/src/gpu/vulkan/SDL_gpu_vulkan.c +++ b/src/gpu/vulkan/SDL_gpu_vulkan.c @@ -793,13 +793,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; @@ -817,18 +817,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; @@ -872,6 +874,8 @@ typedef struct VulkanComputePipelineResourceLayout typedef struct VulkanComputePipeline { + ComputePipelineCommonHeader header; + VkShaderModule shaderModule; VkPipeline pipeline; VulkanComputePipelineResourceLayout *resourceLayout; @@ -1009,25 +1013,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]; @@ -5103,8 +5115,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]; @@ -5127,7 +5139,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]; @@ -5149,7 +5161,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; @@ -5222,8 +5234,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]; @@ -5246,7 +5258,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]; @@ -5268,7 +5280,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; @@ -6541,6 +6553,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; } @@ -6658,6 +6680,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; } @@ -7458,21 +7488,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; } } @@ -7489,12 +7519,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; } } @@ -7511,12 +7541,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; } } @@ -7534,21 +7564,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; } } @@ -7565,12 +7595,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; } } @@ -7589,12 +7619,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); diff --git a/src/joystick/SDL_gamepad.c b/src/joystick/SDL_gamepad.c index 7d8e130389..41472f1988 100644 --- a/src/joystick/SDL_gamepad.c +++ b/src/joystick/SDL_gamepad.c @@ -958,7 +958,7 @@ static GamepadMapping_t *SDL_PrivateMatchGamepadMappingForGUID(SDL_GUID guid, bo // An exact match, including CRC return mapping; } else if (crc && exact_match_crc) { - return NULL; + continue; } if (!best_match) { @@ -1857,6 +1857,11 @@ static GamepadMapping_t *SDL_PrivateGenerateAutomaticGamepadMapping(const char * char name_string[128]; char mapping[1024]; + // Remove the CRC from the GUID + // We already know that this GUID doesn't have a mapping without the CRC, and we want newly + // added mappings without a CRC to override this mapping. + SDL_SetJoystickGUIDCRC(&guid, 0); + // Remove any commas in the name SDL_strlcpy(name_string, name, sizeof(name_string)); { @@ -2878,6 +2883,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; @@ -2886,6 +2892,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(); @@ -2895,6 +2902,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/src/joystick/SDL_gamepad_db.h b/src/joystick/SDL_gamepad_db.h index c6ee1a28ff..94b164f0ea 100644 --- a/src/joystick/SDL_gamepad_db.h +++ b/src/joystick/SDL_gamepad_db.h @@ -215,7 +215,7 @@ static const char *s_GamepadMappings[] = { "03000000362800000100000000000000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,x:b1,y:b2,", "03000000782300000a10000000000000,Onlive Wireless Controller,a:b15,b:b14,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b11,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b13,y:b12,", "030000006b14000001a1000000000000,Orange Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,", - "0300000009120000072f000000000000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:-a2,leftx:a0,lefty:a1,rightx:a3,righty:a4,righttrigger:-a5,start:b11,x:b3,y:b4,", + "0300000009120000072f000000000000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:-a2,leftx:a0,lefty:a1,righttrigger:-a5,rightx:a3,righty:a4,start:b11,x:b3,y:b4,", "03000000120c0000f60e000000000000,P4 Wired Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,", "030000006f0e00000901000000000000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,", "03000000632500002306000000000000,PS Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", @@ -415,13 +415,14 @@ static const char *s_GamepadMappings[] = { "03000000380700008483000000010000,Mad Catz FightStick TE S+ (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,", "03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,", + "03000000853200008906000000010000,NACON Revolution X Unlimited,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", "030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,", "03000000550900001472000025050000,NVIDIA Controller v01.04,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,", "030000004b120000014d000000010000,NYKO AIRFLO EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,", "03000000790000004418000000010000,Nintendo GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,", "030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,", "050000007e05000009200000ff070000,Nintendo Switch Pro Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", - "0300000009120000072f000000010000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a2,leftx:a0,lefty:a1,rightx:a3,righty:a4,righttrigger:a5,start:b11,x:b3,y:b4,", + "0300000009120000072f000000010000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a2,leftx:a0,lefty:a1,righttrigger:a5,rightx:a3,righty:a4,start:b11,x:b3,y:b4,", "030000006f0e00000901000002010000,PDP Versus Fighting Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,", "030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,", "030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,", @@ -796,6 +797,7 @@ static const char *s_GamepadMappings[] = { "03000000c0160000e105000010010000,Xin-Mo Dual Arcade,crc:82d5,a:b1,b:b2,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b8,x:b0,y:b3,", /* Ultimate Atari Fight Stick */ "03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "03000000120c0000101e000011010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", + "03000000120c0000182e000011010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "03000000666600006706000000010000,boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,", "03000000830500006020000010010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "050000006964726f69643a636f6e0000,idroid:con,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", diff --git a/src/joystick/controller_list.h b/src/joystick/controller_list.h index cd476e30d5..63107389cf 100644 --- a/src/joystick/controller_list.h +++ b/src/joystick/controller_list.h @@ -96,6 +96,7 @@ static const ControllerDescription_t arrControllers[] = { { MAKE_CONTROLLER_ID( 0x0c12, 0x0ef6 ), k_eControllerType_PS4Controller, NULL }, // Hitbox Arcade Stick { MAKE_CONTROLLER_ID( 0x0c12, 0x1cf6 ), k_eControllerType_PS4Controller, NULL }, // EMIO PS4 Elite Controller { MAKE_CONTROLLER_ID( 0x0c12, 0x1e10 ), k_eControllerType_PS4Controller, NULL }, // P4 Wired Gamepad generic knock off - lightbar but not trackpad or gyro + { MAKE_CONTROLLER_ID( 0x0c12, 0x2e18 ), k_eControllerType_PS4Controller, NULL }, // ZEROPLUS P4 Wired Gamepad { MAKE_CONTROLLER_ID( 0x0e6f, 0x0203 ), k_eControllerType_PS4Controller, NULL }, // Victrix Pro FS (PS4 peripheral but no trackpad/lightbar) { MAKE_CONTROLLER_ID( 0x0e6f, 0x0207 ), k_eControllerType_PS4Controller, NULL }, // Victrix Pro FS V2 w/ Touchpad for PS4 { MAKE_CONTROLLER_ID( 0x0e6f, 0x020a ), k_eControllerType_PS4Controller, NULL }, // Victrix Pro FS PS4/PS5 (PS4 mode) diff --git a/src/joystick/darwin/SDL_iokitjoystick.c b/src/joystick/darwin/SDL_iokitjoystick.c index 9327276a42..e87ab8243c 100644 --- a/src/joystick/darwin/SDL_iokitjoystick.c +++ b/src/joystick/darwin/SDL_iokitjoystick.c @@ -27,6 +27,7 @@ #include "SDL_iokitjoystick_c.h" #include "../hidapi/SDL_hidapijoystick_c.h" #include "../../haptic/darwin/SDL_syshaptic_c.h" // For haptic hot plugging +#include "../usb_ids.h" #define SDL_JOYSTICK_RUNLOOP_MODE CFSTR("SDLJoystick") @@ -213,6 +214,29 @@ static bool GetHIDScaledCalibratedState(recDevice *pDevice, recElement *pElement return result; } +static bool GetHIDScaledCalibratedState_NACON_Revolution_X_Unlimited(recDevice *pDevice, recElement *pElement, SInt32 min, SInt32 max, SInt32 *pValue) +{ + if (pElement->minReport == 0 && pElement->maxReport == 255) { + return GetHIDScaledCalibratedState(pDevice, pElement, min, max, pValue); + } + + // This device thumbstick axes have an unusual axis range that + // doesn't work with GetHIDScaledCalibratedState() above. + // + // See https://github.com/libsdl-org/SDL/issues/13143 for details + if (GetHIDElementState(pDevice, pElement, pValue)) { + if (*pValue >= 0) { + // Negative axis values range from 32767 (at rest) to 0 (minimum) + *pValue = -32767 + *pValue; + } else if (*pValue < 0) { + // Positive axis values range from -32768 (at rest) to 0 (maximum) + *pValue = 32768 + *pValue; + } + return true; + } + return false; +} + static void JoystickDeviceWasRemovedCallback(void *ctx, IOReturn result, void *sender) { recDevice *device = (recDevice *)ctx; @@ -506,6 +530,11 @@ static bool GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice) pDevice->guid = SDL_CreateJoystickGUID(SDL_HARDWARE_BUS_USB, (Uint16)vendor, (Uint16)product, (Uint16)version, manufacturer_string, product_string, 0, 0); pDevice->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot((Uint16)vendor, (Uint16)product, product_string); + if (vendor == USB_VENDOR_NACON_ALT && + product == USB_PRODUCT_NACON_REVOLUTION_X_UNLIMITED_BT) { + pDevice->nacon_revolution_x_unlimited = true; + } + array = IOHIDDeviceCopyMatchingElements(hidDevice, NULL, kIOHIDOptionsTypeNone); if (array) { AddHIDElements(array, pDevice); @@ -957,7 +986,11 @@ static void DARWIN_JoystickUpdate(SDL_Joystick *joystick) i = 0; while (element) { - goodRead = GetHIDScaledCalibratedState(device, element, -32768, 32767, &value); + if (device->nacon_revolution_x_unlimited) { + goodRead = GetHIDScaledCalibratedState_NACON_Revolution_X_Unlimited(device, element, -32768, 32767, &value); + } else { + goodRead = GetHIDScaledCalibratedState(device, element, -32768, 32767, &value); + } if (goodRead) { SDL_SendJoystickAxis(timestamp, joystick, i, value); } diff --git a/src/joystick/darwin/SDL_iokitjoystick_c.h b/src/joystick/darwin/SDL_iokitjoystick_c.h index 91deb240e4..3a70d2bde1 100644 --- a/src/joystick/darwin/SDL_iokitjoystick_c.h +++ b/src/joystick/darwin/SDL_iokitjoystick_c.h @@ -72,6 +72,7 @@ struct joystick_hwdata int instance_id; SDL_GUID guid; int steam_virtual_gamepad_slot; + bool nacon_revolution_x_unlimited; struct joystick_hwdata *pNext; // next device }; diff --git a/src/joystick/hidapi/SDL_hidapi_gamecube.c b/src/joystick/hidapi/SDL_hidapi_gamecube.c index 130c8287e5..b95fb89c4a 100644 --- a/src/joystick/hidapi/SDL_hidapi_gamecube.c +++ b/src/joystick/hidapi/SDL_hidapi_gamecube.c @@ -31,7 +31,9 @@ #ifdef SDL_JOYSTICK_HIDAPI_GAMECUBE // Define this if you want to log all packets from the controller -// #define DEBUG_GAMECUBE_PROTOCOL +#if 0 +#define DEBUG_GAMECUBE_PROTOCOL +#endif #define MAX_CONTROLLERS 4 @@ -120,22 +122,15 @@ static bool HIDAPI_DriverGameCube_InitDevice(SDL_HIDAPI_Device *device) } device->context = ctx; - ctx->joysticks[0] = 0; - ctx->joysticks[1] = 0; - ctx->joysticks[2] = 0; - ctx->joysticks[3] = 0; ctx->rumble[0] = rumbleMagic; - ctx->useRumbleBrake = false; if (device->vendor_id != USB_VENDOR_NINTENDO) { ctx->pc_mode = true; } if (ctx->pc_mode) { - for (i = 0; i < MAX_CONTROLLERS; ++i) { - ResetAxisRange(ctx, i); - HIDAPI_JoystickConnected(device, &ctx->joysticks[i]); - } + ResetAxisRange(ctx, 0); + HIDAPI_JoystickConnected(device, &ctx->joysticks[0]); } else { // This is all that's needed to initialize the device. Really! if (SDL_hid_write(device->dev, &initMagic, sizeof(initMagic)) != sizeof(initMagic)) { @@ -205,69 +200,61 @@ static void HIDAPI_DriverGameCube_SetDevicePlayerIndex(SDL_HIDAPI_Device *device { } -static void HIDAPI_DriverGameCube_HandleJoystickPacket(SDL_HIDAPI_Device *device, SDL_DriverGameCube_Context *ctx, const Uint8 *packet, int size) +static void HIDAPI_DriverGameCube_HandleJoystickPacket(SDL_HIDAPI_Device *device, SDL_DriverGameCube_Context *ctx, const Uint8 *packet, bool invert_c_stick) { SDL_Joystick *joystick; - Uint8 i, v; + const Uint8 i = 0; // We have a separate context for each connected controller in PC mode, just use the first index + Uint8 v; Sint16 axis_value; Uint64 timestamp = SDL_GetTicksNS(); - if (size != 10) { - return; // How do we handle this packet? - } - - i = packet[0] - 1; - if (i >= MAX_CONTROLLERS) { - return; // How do we handle this packet? - } - joystick = SDL_GetJoystickFromID(ctx->joysticks[i]); if (!joystick) { // Hasn't been opened yet, skip return; } -#define READ_BUTTON(off, flag, button) \ - SDL_SendJoystickButton( \ - timestamp, \ - joystick, \ - button, \ +#define READ_BUTTON(off, flag, button) \ + SDL_SendJoystickButton( \ + timestamp, \ + joystick, \ + button, \ ((packet[off] & flag) != 0)); - READ_BUTTON(1, 0x02, 0) // A - READ_BUTTON(1, 0x04, 1) // B - READ_BUTTON(1, 0x08, 3) // Y - READ_BUTTON(1, 0x01, 2) // X - READ_BUTTON(2, 0x80, 4) // DPAD_LEFT - READ_BUTTON(2, 0x20, 5) // DPAD_RIGHT - READ_BUTTON(2, 0x40, 6) // DPAD_DOWN - READ_BUTTON(2, 0x10, 7) // DPAD_UP - READ_BUTTON(2, 0x02, 8) // START - READ_BUTTON(1, 0x80, 9) // RIGHTSHOULDER + READ_BUTTON(0, 0x02, 0) // A + READ_BUTTON(0, 0x04, 1) // B + READ_BUTTON(0, 0x08, 3) // Y + READ_BUTTON(0, 0x01, 2) // X + READ_BUTTON(1, 0x80, 4) // DPAD_LEFT + READ_BUTTON(1, 0x20, 5) // DPAD_RIGHT + READ_BUTTON(1, 0x40, 6) // DPAD_DOWN + READ_BUTTON(1, 0x10, 7) // DPAD_UP + READ_BUTTON(1, 0x02, 8) // START + READ_BUTTON(0, 0x80, 9) // RIGHTSHOULDER /* These two buttons are for the bottoms of the analog triggers. * More than likely, you're going to want to read the axes instead! * -flibit */ - READ_BUTTON(1, 0x20, 10) // TRIGGERRIGHT - READ_BUTTON(1, 0x10, 11) // TRIGGERLEFT + READ_BUTTON(0, 0x20, 10) // TRIGGERRIGHT + READ_BUTTON(0, 0x10, 11) // TRIGGERLEFT #undef READ_BUTTON -#define READ_AXIS(off, axis, invert) \ - v = invert ? (0xff - packet[off]) : packet[off]; \ - if (v < ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \ - ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = v; \ - if (v > ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \ - ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = v; \ +#define READ_AXIS(off, axis, invert) \ + v = (invert) ? (0xff - packet[off]) : packet[off]; \ + if (v < ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \ + ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = v; \ + if (v > ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis]) \ + ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis] = v; \ axis_value = (Sint16)HIDAPI_RemapVal(v, ctx->min_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis], ctx->max_axis[i * SDL_GAMEPAD_AXIS_COUNT + axis], SDL_MIN_SINT16, SDL_MAX_SINT16); \ - SDL_SendJoystickAxis( \ - timestamp, \ - joystick, \ + SDL_SendJoystickAxis( \ + timestamp, \ + joystick, \ axis, axis_value); - READ_AXIS(3, SDL_GAMEPAD_AXIS_LEFTX, 0) - READ_AXIS(4, SDL_GAMEPAD_AXIS_LEFTY, 1) - READ_AXIS(6, SDL_GAMEPAD_AXIS_RIGHTX, 0) - READ_AXIS(5, SDL_GAMEPAD_AXIS_RIGHTY, 1) - READ_AXIS(7, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, 0) - READ_AXIS(8, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, 0) + READ_AXIS(2, SDL_GAMEPAD_AXIS_LEFTX, 0) + READ_AXIS(3, SDL_GAMEPAD_AXIS_LEFTY, 1) + READ_AXIS(5, SDL_GAMEPAD_AXIS_RIGHTX, invert_c_stick ? 1 : 0) + READ_AXIS(4, SDL_GAMEPAD_AXIS_RIGHTY, invert_c_stick ? 0 : 1) + READ_AXIS(6, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, 0) + READ_AXIS(7, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, 0) #undef READ_AXIS } @@ -366,7 +353,18 @@ static bool HIDAPI_DriverGameCube_UpdateDevice(SDL_HIDAPI_Device *device) HIDAPI_DumpPacket("Nintendo GameCube packet: size = %d", packet, size); #endif if (ctx->pc_mode) { - HIDAPI_DriverGameCube_HandleJoystickPacket(device, ctx, packet, size); + if (size == 10) { + // This is the older firmware + // The first byte is the index of the connected controller + // The C stick has an inverted value range compared to the left stick + HIDAPI_DriverGameCube_HandleJoystickPacket(device, ctx, &packet[1], true); + } else if (size == 9) { + // This is the newer firmware (version 0x7) + // The C stick has the same value range compared to the left stick + HIDAPI_DriverGameCube_HandleJoystickPacket(device, ctx, packet, false); + } else { + // How do we handle this packet? + } } else { HIDAPI_DriverGameCube_HandleNintendoPacket(device, ctx, packet, size); } diff --git a/src/joystick/hidapi/SDL_hidapi_gip.c b/src/joystick/hidapi/SDL_hidapi_gip.c index be1f3f3702..b20dbd41a1 100644 --- a/src/joystick/hidapi/SDL_hidapi_gip.c +++ b/src/joystick/hidapi/SDL_hidapi_gip.c @@ -90,6 +90,9 @@ #define GIP_CMD_GUIDE_COLOR 0x0e #define GIP_SL_ELITE_CONFIG 0x4d +#define GIP_BTN_OFFSET_XBE1 28 +#define GIP_BTN_OFFSET_XBE2 14 + #define GIP_FLAG_FRAGMENT (1u << 7) #define GIP_FLAG_INIT_FRAG (1u << 6) #define GIP_FLAG_SYSTEM (1u << 5) @@ -257,6 +260,7 @@ typedef enum GIP_TYPE_FLIGHT_STICK = 3, GIP_TYPE_NAVIGATION_CONTROLLER = 4, GIP_TYPE_CHATPAD = 5, + GIP_TYPE_HEADSET = 6, } GIP_AttachmentType; typedef enum @@ -268,11 +272,12 @@ typedef enum typedef enum { - GIP_PADDLES_UNKNOWN, - GIP_PADDLES_XBE1, - GIP_PADDLES_XBE2_RAW, - GIP_PADDLES_XBE2, -} GIP_PaddleFormat; + GIP_BTN_FMT_UNKNOWN, + GIP_BTN_FMT_XBE1, + GIP_BTN_FMT_XBE2_RAW, + GIP_BTN_FMT_XBE2_4, + GIP_BTN_FMT_XBE2_5, +} GIP_EliteButtonFormat; /* These come across the wire as little-endian, so let's store them in-memory as such so we can memcmp */ #define MAKE_GUID(NAME, A, B, C, D0, D1, D2, D3, D4, D5, D6, D7) \ @@ -290,6 +295,7 @@ SDL_COMPILE_TIME_ASSERT(GUID, sizeof(GUID) == 16); MAKE_GUID(GUID_ArcadeStick, 0x332054cc, 0xa34b, 0x41d5, 0xa3, 0x4a, 0xa6, 0xa6, 0x71, 0x1e, 0xc4, 0xb3); MAKE_GUID(GUID_DynamicLatencyInput, 0x87f2e56b, 0xc3bb, 0x49b1, 0x82, 0x65, 0xff, 0xff, 0xf3, 0x77, 0x99, 0xee); MAKE_GUID(GUID_FlightStick, 0x03f1a011, 0xefe9, 0x4cc1, 0x96, 0x9c, 0x38, 0xdc, 0x55, 0xf4, 0x04, 0xd0); +MAKE_GUID(GUID_IHeadset, 0xbc25d1a3, 0xc24e, 0x4992, 0x9d, 0xda, 0xef, 0x4f, 0x12, 0x3e, 0xf5, 0xdc); MAKE_GUID(GUID_IConsoleFunctionMap_InputReport, 0xecddd2fe, 0xd387, 0x4294, 0xbd, 0x96, 0x1a, 0x71, 0x2e, 0x3d, 0xc7, 0x7d); MAKE_GUID(GUID_IConsoleFunctionMap_OverflowInputReport, 0x137d4bd0, 0x9347, 0x4472, 0xaa, 0x26, 0x8c, 0x34, 0xa0, 0x8f, 0xf9, 0xbd); MAKE_GUID(GUID_IController, 0x9776ff56, 0x9bfd, 0x4581, 0xad, 0x45, 0xb6, 0x45, 0xbb, 0xa5, 0x26, 0xd6); @@ -308,7 +314,6 @@ MAKE_GUID(GUID_Wheel, 0x646979cf, 0x6b71, 0x4e96, 0x8d, 0xf9, 0x59, 0xe3, 0x98, * MAKE_GUID(GUID_IControllerProfileModeState, 0xf758dc66, 0x022c, 0x48b8, 0xa4, 0xf6, 0x45, 0x7b, 0xa8, 0x0e, 0x2a, 0x5b); * MAKE_GUID(GUID_ICustomAudio, 0x63fd9cc9, 0x94ee, 0x4b5d, 0x9c, 0x4d, 0x8b, 0x86, 0x4c, 0x14, 0x9c, 0xac); * MAKE_GUID(GUID_IExtendedDeviceFlags, 0x34ad9b1e, 0x36ad, 0x4fb5, 0x8a, 0xc7, 0x17, 0x23, 0x4c, 0x9f, 0x54, 0x6f); - * MAKE_GUID(GUID_IHeadset, 0xbc25d1a3, 0xc24e, 0x4992, 0x9d, 0xda, 0xef, 0x4f, 0x12, 0x3e, 0xf5, 0xdc); * MAKE_GUID(GUID_IProgrammableGamepad, 0x31c1034d, 0xb5b7, 0x4551, 0x98, 0x13, 0x87, 0x69, 0xd4, 0xa0, 0xe4, 0xf9); * MAKE_GUID(GUID_IVirtualDevice, 0xdfd26825, 0x110a, 0x4e94, 0xb9, 0x37, 0xb2, 0x7c, 0xe4, 0x7b, 0x25, 0x40); * MAKE_GUID(GUID_OnlineDevAuth, 0x632b1fd1, 0xa3e9, 0x44f9, 0x84, 0x20, 0x5c, 0xe3, 0x44, 0xa0, 0x64, 0x04); @@ -470,12 +475,11 @@ typedef struct GIP_Attachment int altcode_digit; GIP_AttachmentType attachment_type; - GIP_PaddleFormat paddle_format; + GIP_EliteButtonFormat xbe_format; Uint32 features; Uint32 quirks; Uint8 share_button_idx; Uint8 paddle_idx; - int paddle_offset; Uint8 extra_button_idx; int extra_buttons; @@ -779,7 +783,8 @@ static bool GIP_SendVendorMessage( static bool GIP_AttachmentIsController(GIP_Attachment *attachment) { - return attachment->attachment_type != GIP_TYPE_CHATPAD; + return attachment->attachment_type != GIP_TYPE_CHATPAD && + attachment->attachment_type != GIP_TYPE_HEADSET; } static void GIP_MetadataFree(GIP_Metadata *metadata) @@ -1112,9 +1117,30 @@ static bool GIP_FragmentFailed(GIP_Attachment *attachment, const GIP_Header *hea } static bool GIP_EnableEliteButtons(GIP_Attachment *attachment) { - if (attachment->paddle_format == GIP_PADDLES_XBE2_RAW || - (attachment->firmware_major_version != 4 && attachment->firmware_minor_version < 17)) - { + if (attachment->device->device->vendor_id == USB_VENDOR_MICROSOFT) { + if (attachment->device->device->product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_1) { + attachment->xbe_format = GIP_BTN_FMT_XBE1; + } else if (attachment->device->device->product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2) { + if (attachment->firmware_major_version == 4) { + attachment->xbe_format = GIP_BTN_FMT_XBE2_4; + } else if (attachment->firmware_major_version == 5) { + /* + * The exact range for this being necessary is unknown, but it + * starts at 5.11 and at either 5.16 or 5.17. This approach + * still works on 5.21, even if it's not necessary, so having + * a loose upper limit is fine. + */ + if (attachment->firmware_minor_version >= 11 && + attachment->firmware_minor_version < 17) + { + attachment->xbe_format = GIP_BTN_FMT_XBE2_RAW; + } else { + attachment->xbe_format = GIP_BTN_FMT_XBE2_5; + } + } + } + } + if (attachment->xbe_format == GIP_BTN_FMT_XBE2_RAW) { /* * The meaning of this packet is unknown and not documented, but it's * needed for the Elite 2 controller to send raw reports @@ -1180,10 +1206,9 @@ static bool GIP_SendInitSequence(GIP_Attachment *attachment) { return false; } - - if (!GIP_EnableEliteButtons(attachment)) { - return false; - } + } + if (!GIP_EnableEliteButtons(attachment)) { + return false; } if (!GIP_SendSetDeviceState(attachment, GIP_STATE_START)) { return false; @@ -1387,17 +1412,71 @@ static bool GIP_HandleCommandStatusDevice( const Uint8 *bytes, int num_bytes) { - GIP_ExtendedStatus status = {{0}}; + GIP_ExtendedStatus status; + SDL_Joystick *joystick = NULL; + SDL_PowerState power_state; + int power_percent = 0; int i; if (num_bytes < 1) { return false; } + SDL_zero(status); status.base.battery_level = bytes[0] & 3; status.base.battery_type = (bytes[0] >> 2) & 3; status.base.charge = (bytes[0] >> 4) & 3; status.base.power_level = (bytes[0] >> 6) & 3; + if (attachment->joystick) { + joystick = SDL_GetJoystickFromID(attachment->joystick); + } + if (joystick) { + switch (status.base.battery_level) { + case GIP_BATTERY_CRITICAL: + power_percent = 1; + break; + case GIP_BATTERY_LOW: + power_percent = 25; + break; + case GIP_BATTERY_MEDIUM: + power_percent = 50; + break; + case GIP_BATTERY_FULL: + power_percent = 100; + break; + } + switch (status.base.charge) { + case GIP_CHARGING: + if (status.base.battery_level == GIP_BATTERY_FULL) { + power_state = SDL_POWERSTATE_CHARGED; + } else { + power_state = SDL_POWERSTATE_CHARGING; + } + break; + case GIP_NOT_CHARGING: + power_state = SDL_POWERSTATE_ON_BATTERY; + break; + case GIP_CHARGE_ERROR: + default: + power_state = SDL_POWERSTATE_UNKNOWN; + break; + } + + switch (status.base.battery_type) { + case GIP_BATTERY_ABSENT: + power_state = SDL_POWERSTATE_NO_BATTERY; + break; + case GIP_BATTERY_STANDARD: + case GIP_BATTERY_RECHARGEABLE: + break; + default: + power_state = SDL_POWERSTATE_UNKNOWN; + break; + } + + SDL_SendJoystickPowerInfo(joystick, power_state, power_percent); + } + if (num_bytes >= 4) { status.device_active = bytes[1] & 1; if (bytes[1] & 2) { @@ -1510,6 +1589,11 @@ static bool GIP_HandleCommandMetadataRespose( attachment->attachment_type = GIP_TYPE_CHATPAD; break; } + if (SDL_strcmp(type, "Windows.Xbox.Input.Headset") == 0) { + attachment->attachment_type = GIP_TYPE_HEADSET; + expected_guid = &GUID_IHeadset; + break; + } } found_expected_guid = !expected_guid; @@ -1654,11 +1738,6 @@ static bool GIP_HandleCommandFirmware( if (attachment->device->device->vendor_id == USB_VENDOR_MICROSOFT && attachment->device->device->product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2) { - if (attachment->firmware_major_version == 5 && attachment->firmware_minor_version < 17) { - attachment->paddle_format = GIP_PADDLES_XBE2_RAW; - } else { - attachment->paddle_format = GIP_PADDLES_XBE2; - } return GIP_EnableEliteButtons(attachment); } return true; @@ -1687,28 +1766,47 @@ static bool GIP_HandleCommandRawReport( return true; } - if (num_bytes < 17 || num_bytes <= attachment->paddle_offset) { + if (num_bytes < 17) { SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "GIP: Discarding too-short raw report"); return false; } - if ((attachment->features & GIP_FEATURE_ELITE_BUTTONS) && attachment->paddle_format == GIP_PADDLES_XBE2_RAW) { - SDL_SendJoystickButton(timestamp, - joystick, - attachment->paddle_idx, - (bytes[attachment->paddle_offset] & 0x01) != 0); - SDL_SendJoystickButton(timestamp, - joystick, - attachment->paddle_idx + 1, - (bytes[attachment->paddle_offset] & 0x02) != 0); - SDL_SendJoystickButton(timestamp, - joystick, - attachment->paddle_idx + 2, - (bytes[attachment->paddle_offset] & 0x04) != 0); - SDL_SendJoystickButton(timestamp, - joystick, - attachment->paddle_idx + 3, - (bytes[attachment->paddle_offset] & 0x08) != 0); + if ((attachment->features & GIP_FEATURE_ELITE_BUTTONS) && attachment->xbe_format == GIP_BTN_FMT_XBE2_RAW) { + if (bytes[15] & 3) { + SDL_SendJoystickButton(timestamp, + joystick, + attachment->paddle_idx, + 0); + SDL_SendJoystickButton(timestamp, + joystick, + attachment->paddle_idx + 1, + 0); + SDL_SendJoystickButton(timestamp, + joystick, + attachment->paddle_idx + 2, + 0); + SDL_SendJoystickButton(timestamp, + joystick, + attachment->paddle_idx + 3, + 0); + } else { + SDL_SendJoystickButton(timestamp, + joystick, + attachment->paddle_idx, + (bytes[GIP_BTN_OFFSET_XBE2] & 0x01) != 0); + SDL_SendJoystickButton(timestamp, + joystick, + attachment->paddle_idx + 1, + (bytes[GIP_BTN_OFFSET_XBE2] & 0x02) != 0); + SDL_SendJoystickButton(timestamp, + joystick, + attachment->paddle_idx + 2, + (bytes[GIP_BTN_OFFSET_XBE2] & 0x04) != 0); + SDL_SendJoystickButton(timestamp, + joystick, + attachment->paddle_idx + 3, + (bytes[GIP_BTN_OFFSET_XBE2] & 0x08) != 0); + } } return true; } @@ -2073,46 +2171,78 @@ static bool GIP_HandleLLInputReport( break; } - if ((attachment->features & GIP_FEATURE_ELITE_BUTTONS) && - num_bytes > attachment->paddle_offset && - attachment->last_input[attachment->paddle_offset] != bytes[attachment->paddle_offset]) - { - if (attachment->paddle_format == GIP_PADDLES_XBE1) { - if (bytes[attachment->paddle_offset] & 0x10) { - SDL_SendJoystickButton(timestamp, - joystick, - attachment->paddle_idx, - (bytes[attachment->paddle_offset] & 0x02) != 0); - SDL_SendJoystickButton(timestamp, - joystick, - attachment->paddle_idx + 1, - (bytes[attachment->paddle_offset] & 0x08) != 0); - SDL_SendJoystickButton(timestamp, - joystick, - attachment->paddle_idx + 2, - (bytes[attachment->paddle_offset] & 0x01) != 0); - SDL_SendJoystickButton(timestamp, - joystick, - attachment->paddle_idx + 3, - (bytes[attachment->paddle_offset] & 0x04) != 0); - } - } else if (attachment->paddle_format == GIP_PADDLES_XBE2) { + if (attachment->features & GIP_FEATURE_ELITE_BUTTONS) { + bool clear = false; + if (attachment->xbe_format == GIP_BTN_FMT_XBE1 && + num_bytes > GIP_BTN_OFFSET_XBE1 && + attachment->last_input[GIP_BTN_OFFSET_XBE1] != bytes[GIP_BTN_OFFSET_XBE1] && + (bytes[GIP_BTN_OFFSET_XBE1] & 0x10)) + { SDL_SendJoystickButton(timestamp, joystick, attachment->paddle_idx, - (bytes[attachment->paddle_offset] & 0x01) != 0); + (bytes[GIP_BTN_OFFSET_XBE1] & 0x02) != 0); SDL_SendJoystickButton(timestamp, joystick, attachment->paddle_idx + 1, - (bytes[attachment->paddle_offset] & 0x02) != 0); + (bytes[GIP_BTN_OFFSET_XBE1] & 0x08) != 0); SDL_SendJoystickButton(timestamp, joystick, attachment->paddle_idx + 2, - (bytes[attachment->paddle_offset] & 0x04) != 0); + (bytes[GIP_BTN_OFFSET_XBE1] & 0x01) != 0); SDL_SendJoystickButton(timestamp, joystick, attachment->paddle_idx + 3, - (bytes[attachment->paddle_offset] & 0x08) != 0); + (bytes[GIP_BTN_OFFSET_XBE1] & 0x04) != 0); + } else if ((attachment->xbe_format == GIP_BTN_FMT_XBE2_4 || + attachment->xbe_format == GIP_BTN_FMT_XBE2_5) && + num_bytes > GIP_BTN_OFFSET_XBE2) + { + int profile_offset = attachment->xbe_format == GIP_BTN_FMT_XBE2_4 ? 15 : 20; + if (attachment->last_input[GIP_BTN_OFFSET_XBE2] != bytes[GIP_BTN_OFFSET_XBE2] || + attachment->last_input[profile_offset] != bytes[profile_offset]) + { + if (bytes[profile_offset] & 3) { + clear = true; + } else { + SDL_SendJoystickButton(timestamp, + joystick, + attachment->paddle_idx, + (bytes[GIP_BTN_OFFSET_XBE2] & 0x01) != 0); + SDL_SendJoystickButton(timestamp, + joystick, + attachment->paddle_idx + 1, + (bytes[GIP_BTN_OFFSET_XBE2] & 0x02) != 0); + SDL_SendJoystickButton(timestamp, + joystick, + attachment->paddle_idx + 2, + (bytes[GIP_BTN_OFFSET_XBE2] & 0x04) != 0); + SDL_SendJoystickButton(timestamp, + joystick, + attachment->paddle_idx + 3, + (bytes[GIP_BTN_OFFSET_XBE2] & 0x08) != 0); + } + } + } else { + clear = true; + } + if (clear) { + SDL_SendJoystickButton(timestamp, + joystick, + attachment->paddle_idx, + 0); + SDL_SendJoystickButton(timestamp, + joystick, + attachment->paddle_idx + 1, + 0); + SDL_SendJoystickButton(timestamp, + joystick, + attachment->paddle_idx + 2, + 0); + SDL_SendJoystickButton(timestamp, + joystick, + attachment->paddle_idx + 3, + 0); } } @@ -2586,19 +2716,11 @@ static bool HIDAPI_DriverGIP_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joystic // Initialize the joystick capabilities joystick->nbuttons = 11; - if (device->vendor_id == USB_VENDOR_MICROSOFT) { - if (device->product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_1) { - attachment->paddle_offset = 28; - attachment->paddle_format = GIP_PADDLES_XBE1; - } else if (device->product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2) { - attachment->paddle_offset = 14; - attachment->paddle_format = GIP_PADDLES_XBE2; - if (attachment->firmware_major_version == 5 && attachment->firmware_minor_version < 17) { - attachment->paddle_format = GIP_PADDLES_XBE2_RAW; - } - } - } - if (attachment->paddle_offset > 0) { + GIP_EnableEliteButtons(attachment); + if (attachment->xbe_format != GIP_BTN_FMT_UNKNOWN || + (device->vendor_id == USB_VENDOR_MICROSOFT && + device->product_id == USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2)) + { attachment->paddle_idx = (Uint8) joystick->nbuttons; joystick->nbuttons += 4; } diff --git a/src/joystick/usb_ids.h b/src/joystick/usb_ids.h index 4a80c948cd..33a8a6cb7e 100644 --- a/src/joystick/usb_ids.h +++ b/src/joystick/usb_ids.h @@ -91,6 +91,7 @@ #define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS4_WIRED 0x0d17 #define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS5_WIRELESS 0x0d18 #define USB_PRODUCT_NACON_REVOLUTION_5_PRO_PS5_WIRED 0x0d19 +#define USB_PRODUCT_NACON_REVOLUTION_X_UNLIMITED_BT 0x0689 #define USB_PRODUCT_NINTENDO_GAMECUBE_ADAPTER 0x0337 #define USB_PRODUCT_NINTENDO_N64_CONTROLLER 0x2019 #define USB_PRODUCT_NINTENDO_SEGA_GENESIS_CONTROLLER 0x201e diff --git a/src/render/ngage/SDL_render_ngage.cpp b/src/render/ngage/SDL_render_ngage.cpp index 1717f3635b..05c773e331 100644 --- a/src/render/ngage/SDL_render_ngage.cpp +++ b/src/render/ngage/SDL_render_ngage.cpp @@ -69,6 +69,8 @@ void NGAGE_DestroyTextureData(NGAGE_TextureData *data) if (data) { delete data->bitmap; data->bitmap = NULL; + delete data->mask; + data->mask = NULL; } } @@ -350,7 +352,29 @@ bool CRenderer::Copy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rec if (phdata->bitmap) { TRect aSource(TPoint(srcrect->x, srcrect->y), TSize(srcrect->w, srcrect->h)); TPoint aDest(dstrect->x, dstrect->y); - iRenderer->Gc()->BitBlt(aDest, phdata->bitmap, aSource); + + w = phdata->surface->w; + pitch = phdata->surface->pitch; + Uint16 *src = (Uint16 *)phdata->surface->pixels; + Uint16 *mask = (Uint16 *)phdata->mask->DataAddress(); + + for (int y = 0; y < srcrect->h; ++y) { + int src_y = srcrect->y + y; + if (src_y < 0 || src_y >= phdata->surface->h) { + continue; + } + for (int x = 0; x < srcrect->w; ++x) { + int src_x = srcrect->x + x; + if (src_x < 0 || src_x >= phdata->surface->w) { + continue; + } + Uint16 pixel = src[src_y * (pitch / 2) + src_x]; + Uint8 alpha = (pixel & 0xF000) >> 12; + mask[src_y * w + src_x] = (alpha == 0) ? 0x0000 : 0xFFFF; + } + } + + iRenderer->Gc()->BitBltMasked(aDest, phdata->bitmap, aSource, phdata->mask, EFalse); } return true; @@ -416,7 +440,29 @@ bool CRenderer::CopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const NGAGE if (phdata->bitmap) { TRect aSource(TPoint(copydata->srcrect.x, copydata->srcrect.y), TSize(copydata->srcrect.w, copydata->srcrect.h)); TPoint aDest(copydata->dstrect.x, copydata->dstrect.y); - iRenderer->Gc()->BitBlt(aDest, phdata->bitmap, aSource); + + w = phdata->surface->w; + pitch = phdata->surface->pitch; + Uint16 *src = (Uint16 *)phdata->surface->pixels; + Uint16 *mask = (Uint16 *)phdata->mask->DataAddress(); + + for (int y = 0; y < copydata->srcrect.h; ++y) { + int src_y = copydata->srcrect.y + y; + if (src_y < 0 || src_y >= phdata->surface->h) { + continue; + } + for (int x = 0; x < copydata->srcrect.w; ++x) { + int src_x = copydata->srcrect.x + x; + if (src_x < 0 || src_x >= phdata->surface->w) { + continue; + } + Uint16 pixel = src[src_y * (pitch / 2) + src_x]; + Uint8 alpha = (pixel & 0xF000) >> 12; + mask[src_y * w + src_x] = (alpha == 0) ? 0x0000 : 0xFFFF; + } + } + + iRenderer->Gc()->BitBltMasked(aDest, phdata->bitmap, aSource, phdata->mask, EFalse); } return true; @@ -440,6 +486,18 @@ bool CRenderer::CreateTextureData(NGAGE_TextureData *aTextureData, const TInt aW return false; } + aTextureData->mask = new CFbsBitmap(); + if (!aTextureData->mask) { + return false; + } + + error = aTextureData->mask->Create(TSize(aWidth, aHeight), EColor4K); + if (error != KErrNone) { + delete aTextureData->mask; + aTextureData->mask = NULL; + return false; + } + return true; } diff --git a/src/render/ngage/SDL_render_ngage_c.h b/src/render/ngage/SDL_render_ngage_c.h index 2adab73398..69bfbdd894 100644 --- a/src/render/ngage/SDL_render_ngage_c.h +++ b/src/render/ngage/SDL_render_ngage_c.h @@ -58,6 +58,7 @@ typedef struct CFbsBitmap CFbsBitmap; typedef struct NGAGE_TextureData { CFbsBitmap *bitmap; + CFbsBitmap *mask; SDL_Surface *surface; } NGAGE_TextureData; diff --git a/src/timer/ngage/SDL_systimer.cpp b/src/timer/ngage/SDL_systimer.cpp index d2e1cce904..f3039bd0ec 100644 --- a/src/timer/ngage/SDL_systimer.cpp +++ b/src/timer/ngage/SDL_systimer.cpp @@ -29,12 +29,13 @@ extern "C" { Uint64 SDL_GetPerformanceCounter(void) { - return (Uint64)User::TickCount(); + return static_cast(User::TickCount()); } Uint64 SDL_GetPerformanceFrequency(void) { - return (Uint64)1000000u; + // On Symbian S60v1, tick frequency is 64 Hz => 1 tick = 15,625 microseconds. + return 64; } void SDL_SYS_DelayNS(Uint64 ns) diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index f61dc0e8f8..de27882901 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -33,6 +33,7 @@ #include "../SDL_sysvideo.h" #include "SDL_windowsvideo.h" +#include "SDL_windowskeyboard.h" #include "SDL_windowswindow.h" // Dropfile support @@ -780,6 +781,9 @@ bool WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Properties return false; } + // Ensure that the IME isn't active on the new window until explicitly requested. + WIN_StopTextInput(_this, window); + // Inform Windows of the frame change so we can respond to WM_NCCALCSIZE SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE); diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index cd10c8f8b2..b00e4c1ce0 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -86,6 +86,23 @@ static Bool X11_XIfEventTimeout(Display *display, XEvent *event_return, Bool (*p } */ +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 bool X11_IsWindowMapped(SDL_VideoDevice *_this, SDL_Window *window) { SDL_WindowData *data = window->internal; @@ -1576,6 +1593,15 @@ void X11_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) X11_XMoveWindow(display, data->xwindow, x, y); } + /* XMonad ignores size hints and shrinks the client area to overlay borders on fixed-size windows, + * even if no borders were requested, resulting in the window client area being smaller than + * requested. Calling XResizeWindow after mapping seems to fix it, even though resizing fixed-size + * windows in this manner doesn't work on any other window manager. + */ + if (!(window->flags & SDL_WINDOW_RESIZABLE) && X11_CheckCurrentDesktop("xmonad")) { + X11_XResizeWindow(display, data->xwindow, window->w, window->h); + } + /* Some window managers can send garbage coordinates while mapping the window, so don't emit size and position * events during the initial configure events. */