Added support for custom shaders with the GPU renderer
Added an example of MSDF font rendering with the SDL 2D renderer
This commit is contained in:
parent
eb56c8af85
commit
2aee105b43
19 changed files with 1460 additions and 34 deletions
|
@ -346,6 +346,16 @@ static bool FlushRenderCommandsIfTextureNeeded(SDL_Texture *texture)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool FlushRenderCommandsIfGPURenderStateNeeded(SDL_GPURenderState *state)
|
||||
{
|
||||
SDL_Renderer *renderer = state->renderer;
|
||||
if (state->last_command_generation == renderer->render_command_generation) {
|
||||
// the current command queue depends on this state, flush the queue now before it changes
|
||||
return FlushRenderCommands(renderer);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SDL_FlushRenderer(SDL_Renderer *renderer)
|
||||
{
|
||||
if (!FlushRenderCommands(renderer)) {
|
||||
|
@ -577,6 +587,10 @@ static SDL_RenderCommand *PrepQueueCmdDraw(SDL_Renderer *renderer, const SDL_Ren
|
|||
cmd->data.draw.texture_scale_mode = texture->scaleMode;
|
||||
}
|
||||
cmd->data.draw.texture_address_mode = SDL_TEXTURE_ADDRESS_CLAMP;
|
||||
cmd->data.draw.gpu_render_state = renderer->gpu_render_state;
|
||||
if (renderer->gpu_render_state) {
|
||||
renderer->gpu_render_state->last_command_generation = renderer->render_command_generation;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cmd;
|
||||
|
@ -5824,3 +5838,142 @@ bool SDL_GetDefaultTextureScaleMode(SDL_Renderer *renderer, SDL_ScaleMode *scale
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
SDL_GPURenderState *SDL_CreateGPURenderState(SDL_Renderer *renderer, SDL_GPURenderStateDesc *desc)
|
||||
{
|
||||
CHECK_RENDERER_MAGIC(renderer, false);
|
||||
|
||||
if (!desc) {
|
||||
SDL_InvalidParamError("desc");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (desc->version < sizeof(*desc)) {
|
||||
// Update this to handle older versions of this interface
|
||||
SDL_SetError("Invalid desc, should be initialized with SDL_INIT_INTERFACE()");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!desc->fragment_shader) {
|
||||
SDL_SetError("desc->fragment_shader is required");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_GPUDevice *device = (SDL_GPUDevice *)SDL_GetPointerProperty(renderer->props, SDL_PROP_RENDERER_GPU_DEVICE_POINTER, NULL);
|
||||
if (!device) {
|
||||
SDL_SetError("Renderer isn't associated with a GPU device");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_GPURenderState *state = (SDL_GPURenderState *)SDL_calloc(1, sizeof(*state));
|
||||
if (!state) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state->renderer = renderer;
|
||||
state->fragment_shader = desc->fragment_shader;
|
||||
|
||||
if (desc->num_sampler_bindings > 0) {
|
||||
state->sampler_bindings = (SDL_GPUTextureSamplerBinding *)SDL_calloc(desc->num_sampler_bindings, sizeof(*state->sampler_bindings));
|
||||
if (!state->sampler_bindings) {
|
||||
SDL_DestroyGPURenderState(state);
|
||||
return NULL;
|
||||
}
|
||||
SDL_memcpy(state->sampler_bindings, desc->sampler_bindings, desc->num_sampler_bindings * sizeof(*state->sampler_bindings));
|
||||
state->num_sampler_bindings = desc->num_sampler_bindings;
|
||||
}
|
||||
|
||||
if (desc->num_storage_textures > 0) {
|
||||
state->storage_textures = (SDL_GPUTexture **)SDL_calloc(desc->num_storage_textures, sizeof(*state->storage_textures));
|
||||
if (!state->storage_textures) {
|
||||
SDL_DestroyGPURenderState(state);
|
||||
return NULL;
|
||||
}
|
||||
SDL_memcpy(state->storage_textures, desc->storage_textures, desc->num_storage_textures * sizeof(*state->storage_textures));
|
||||
state->num_storage_textures = desc->num_storage_textures;
|
||||
}
|
||||
|
||||
if (desc->num_storage_buffers > 0) {
|
||||
state->storage_buffers = (SDL_GPUBuffer **)SDL_calloc(desc->num_storage_buffers, sizeof(*state->storage_buffers));
|
||||
if (!state->storage_buffers) {
|
||||
SDL_DestroyGPURenderState(state);
|
||||
return NULL;
|
||||
}
|
||||
SDL_memcpy(state->storage_buffers, desc->storage_buffers, desc->num_storage_buffers * sizeof(*state->storage_buffers));
|
||||
state->num_storage_buffers = desc->num_storage_buffers;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
bool SDL_SetGPURenderStateFragmentUniformData(SDL_GPURenderState *state, Uint32 slot_index, const void *data, Uint32 length)
|
||||
{
|
||||
if (!state) {
|
||||
return SDL_InvalidParamError("state");
|
||||
}
|
||||
|
||||
if (!FlushRenderCommandsIfGPURenderStateNeeded(state)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < state->num_uniform_buffers; i++) {
|
||||
SDL_GPURenderStateUniformBuffer *buffer = &state->uniform_buffers[i];
|
||||
if (buffer->slot_index == slot_index) {
|
||||
void *new_data = SDL_realloc(buffer->data, length);
|
||||
if (!new_data) {
|
||||
return false;
|
||||
}
|
||||
SDL_memcpy(new_data, data, length);
|
||||
buffer->data = new_data;
|
||||
buffer->length = length;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_GPURenderStateUniformBuffer *buffers = (SDL_GPURenderStateUniformBuffer *)SDL_realloc(state->uniform_buffers, (state->num_uniform_buffers + 1) * sizeof(*state->uniform_buffers));
|
||||
if (!buffers) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_GPURenderStateUniformBuffer *buffer = &buffers[state->num_uniform_buffers];
|
||||
buffer->slot_index = slot_index;
|
||||
buffer->length = length;
|
||||
buffer->data = SDL_malloc(length);
|
||||
if (!buffer->data) {
|
||||
SDL_free(buffers);
|
||||
return false;
|
||||
}
|
||||
SDL_memcpy(buffer->data, data, length);
|
||||
|
||||
state->uniform_buffers = buffers;
|
||||
++state->num_uniform_buffers;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SDL_SetRenderGPUState(SDL_Renderer *renderer, SDL_GPURenderState *state)
|
||||
{
|
||||
CHECK_RENDERER_MAGIC(renderer, false);
|
||||
|
||||
renderer->gpu_render_state = state;
|
||||
return true;
|
||||
}
|
||||
|
||||
void SDL_DestroyGPURenderState(SDL_GPURenderState *state)
|
||||
{
|
||||
if (!state) {
|
||||
return;
|
||||
}
|
||||
|
||||
FlushRenderCommandsIfGPURenderStateNeeded(state);
|
||||
|
||||
if (state->num_uniform_buffers > 0) {
|
||||
for (int i = 0; i < state->num_uniform_buffers; i++) {
|
||||
SDL_free(state->uniform_buffers[i].data);
|
||||
}
|
||||
SDL_free(state->uniform_buffers);
|
||||
}
|
||||
SDL_free(state->sampler_bindings);
|
||||
SDL_free(state->storage_textures);
|
||||
SDL_free(state->storage_buffers);
|
||||
SDL_free(state);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue