diff --git a/include/SDL3/SDL_render.h b/include/SDL3/SDL_render.h index 986130ce46..4f39e19e6b 100644 --- a/include/SDL3/SDL_render.h +++ b/include/SDL3/SDL_render.h @@ -2967,6 +2967,63 @@ typedef struct SDL_GPURenderState SDL_GPURenderState; */ extern SDL_DECLSPEC SDL_GPURenderState * SDLCALL SDL_CreateGPURenderState(SDL_Renderer *renderer, const SDL_GPURenderStateCreateInfo *createinfo); +/** + * Set sampler bindings variables in a custom GPU render state. + * + * The data is copied and will be binded using + * SDL_BindGPUFragmentSamplers() during draw call execution. + * + * \param state the state to modify. + * \param num_sampler_bindings The number of additional fragment samplers to bind + * \param sampler_bindings Additional fragment samplers to bind + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * renderer. + * + * \since This function is available since SDL 3.4.x. + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetGPURenderStateSamplerBindings(SDL_GPURenderState *state, int num_sampler_bindings, const SDL_GPUTextureSamplerBinding *sampler_bindings); + +/** + * Set storage textures variables in a custom GPU render state. + * + * The data is copied and will be binded using + * SDL_BindGPUFragmentStorageTextures() during draw call execution. + * + * \param state the state to modify. + * \param num_storage_textures The number of storage textures to bind + * \param storage_textures Storage textures to bind + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * renderer. + * + * \since This function is available since SDL 3.4.x. + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetGPURenderStateStorageTextures(SDL_GPURenderState *state, int num_storage_textures, SDL_GPUTexture *const *storage_textures); + +/** + * Set storage buffers variables in a custom GPU render state. + * + * The data is copied and will be binded using + * SDL_BindGPUFragmentStorageBuffers() during draw call execution. + * + * \param state the state to modify. + * \param num_storage_buffers The number of storage buffers to bind + * \param storage_buffers Storage buffers to bind + * \returns true on success or false on failure; call SDL_GetError() for more + * information. + * + * \threadsafety This function should be called on the thread that created the + * renderer. + * + * \since This function is available since SDL 3.4.x. + */ +extern SDL_DECLSPEC bool SDLCALL SDL_SetGPURenderStateStorageBuffers(SDL_GPURenderState *state, int num_storage_buffers, SDL_GPUBuffer *const *storage_buffers); + /** * Set fragment shader uniform variables in a custom GPU render state. * diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 86ff0a684b..184f8708ea 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -1280,6 +1280,9 @@ SDL3_0.0.0 { SDL_OpenXR_UnloadLibrary; SDL_OpenXR_GetXrGetInstanceProcAddr; SDL_CreateTrayWithProperties; + SDL_SetGPURenderStateSamplerBindings; + SDL_SetGPURenderStateStorageTextures; + SDL_SetGPURenderStateStorageBuffers; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index acee86998e..87762e6d7a 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -1306,3 +1306,6 @@ #define SDL_OpenXR_UnloadLibrary SDL_OpenXR_UnloadLibrary_REAL #define SDL_OpenXR_GetXrGetInstanceProcAddr SDL_OpenXR_GetXrGetInstanceProcAddr_REAL #define SDL_CreateTrayWithProperties SDL_CreateTrayWithProperties_REAL +#define SDL_SetGPURenderStateSamplerBindings SDL_SetGPURenderStateSamplerBindings_REAL +#define SDL_SetGPURenderStateStorageTextures SDL_SetGPURenderStateStorageTextures_REAL +#define SDL_SetGPURenderStateStorageBuffers SDL_SetGPURenderStateStorageBuffers_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 68dca5a192..d965c7b628 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -1314,3 +1314,6 @@ SDL_DYNAPI_PROC(bool,SDL_OpenXR_LoadLibrary,(void),(),return) SDL_DYNAPI_PROC(void,SDL_OpenXR_UnloadLibrary,(void),(),) SDL_DYNAPI_PROC(PFN_xrGetInstanceProcAddr,SDL_OpenXR_GetXrGetInstanceProcAddr,(void),(),return) SDL_DYNAPI_PROC(SDL_Tray*,SDL_CreateTrayWithProperties,(SDL_PropertiesID a),(a),return) +SDL_DYNAPI_PROC(bool,SDL_SetGPURenderStateSamplerBindings,(SDL_GPURenderState *a,int b,const SDL_GPUTextureSamplerBinding *c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetGPURenderStateStorageTextures,(SDL_GPURenderState *a,int b,SDL_GPUTexture *const*c),(a,b,c),return) +SDL_DYNAPI_PROC(bool,SDL_SetGPURenderStateStorageBuffers,(SDL_GPURenderState *a,int b,SDL_GPUBuffer *const*c),(a,b,c),return) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 8338255250..684ad7b82d 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -6210,6 +6210,72 @@ SDL_GPURenderState *SDL_CreateGPURenderState(SDL_Renderer *renderer, const SDL_G return state; } +bool SDL_SetGPURenderStateSamplerBindings(SDL_GPURenderState *state, int num_sampler_bindings, const SDL_GPUTextureSamplerBinding *sampler_bindings) +{ + if (!state) { + return SDL_InvalidParamError("state"); + } + + if (!FlushRenderCommandsIfGPURenderStateNeeded(state)) { + return false; + } + + Sint32 length = sizeof(SDL_GPUTextureSamplerBinding) * num_sampler_bindings; + SDL_GPUTextureSamplerBinding *new_sampler_bindings = (SDL_GPUTextureSamplerBinding *)SDL_realloc(state->sampler_bindings, length); + if (!new_sampler_bindings) { + return false; + } + SDL_memcpy(new_sampler_bindings, sampler_bindings, length); + state->num_sampler_bindings = num_sampler_bindings; + state->sampler_bindings = new_sampler_bindings; + + return true; +} + +bool SDL_SetGPURenderStateStorageTextures(SDL_GPURenderState *state, int num_storage_textures, SDL_GPUTexture *const *storage_textures) +{ + if (!state) { + return SDL_InvalidParamError("state"); + } + + if (!FlushRenderCommandsIfGPURenderStateNeeded(state)) { + return false; + } + + Sint32 length = sizeof(SDL_GPUTexture *) * num_storage_textures; + SDL_GPUTexture **new_storage_textures = (SDL_GPUTexture **)SDL_realloc(state->storage_textures, length); + if (!new_storage_textures) { + return false; + } + SDL_memcpy(new_storage_textures, storage_textures, length); + state->num_storage_textures = num_storage_textures; + state->storage_textures = new_storage_textures; + + return true; +} + +bool SDL_SetGPURenderStateStorageBuffers(SDL_GPURenderState *state, int num_storage_buffers, SDL_GPUBuffer *const *storage_buffers) +{ + if (!state) { + return SDL_InvalidParamError("state"); + } + + if (!FlushRenderCommandsIfGPURenderStateNeeded(state)) { + return false; + } + + Sint32 length = sizeof(SDL_GPUBuffer *) * num_storage_buffers; + SDL_GPUBuffer **new_storage_buffers = (SDL_GPUBuffer **)SDL_realloc(state->storage_buffers, length); + if (!new_storage_buffers) { + return false; + } + SDL_memcpy(new_storage_buffers, storage_buffers, length); + state->num_storage_buffers = num_storage_buffers; + state->storage_buffers = new_storage_buffers; + + return true; +} + bool SDL_SetGPURenderStateFragmentUniforms(SDL_GPURenderState *state, Uint32 slot_index, const void *data, Uint32 length) { if (!state) {