summaryrefslogtreecommitdiff
path: root/contrib/SDL-3.2.8/src/render/gpu/SDL_pipeline_gpu.c
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2025-12-27 12:03:39 -0800
committer3gg <3gg@shellblade.net>2025-12-27 12:03:39 -0800
commit5a079a2d114f96d4847d1ee305d5b7c16eeec50e (patch)
tree8926ab44f168acf787d8e19608857b3af0f82758 /contrib/SDL-3.2.8/src/render/gpu/SDL_pipeline_gpu.c
Initial commit
Diffstat (limited to 'contrib/SDL-3.2.8/src/render/gpu/SDL_pipeline_gpu.c')
-rw-r--r--contrib/SDL-3.2.8/src/render/gpu/SDL_pipeline_gpu.c202
1 files changed, 202 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/src/render/gpu/SDL_pipeline_gpu.c b/contrib/SDL-3.2.8/src/render/gpu/SDL_pipeline_gpu.c
new file mode 100644
index 0000000..0783374
--- /dev/null
+++ b/contrib/SDL-3.2.8/src/render/gpu/SDL_pipeline_gpu.c
@@ -0,0 +1,202 @@
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20*/
21#include "SDL_internal.h"
22
23#ifdef SDL_VIDEO_RENDER_GPU
24
25#include "SDL_gpu_util.h"
26#include "SDL_pipeline_gpu.h"
27
28#include "../SDL_sysrender.h"
29
30struct GPU_PipelineCacheKeyStruct
31{
32 Uint64 blend_mode : 28;
33 Uint64 frag_shader : 4;
34 Uint64 vert_shader : 4;
35 Uint64 attachment_format : 6;
36 Uint64 primitive_type : 3;
37};
38
39typedef union GPU_PipelineCacheKeyConverter
40{
41 struct GPU_PipelineCacheKeyStruct as_struct;
42 Uint64 as_uint64;
43} GPU_PipelineCacheKeyConverter;
44
45SDL_COMPILE_TIME_ASSERT(GPU_PipelineCacheKeyConverter_Size, sizeof(GPU_PipelineCacheKeyConverter) <= sizeof(Uint64));
46
47static Uint32 SDLCALL HashPipelineCacheKey(void *userdata, const void *key)
48{
49 const GPU_PipelineParameters *params = (const GPU_PipelineParameters *) key;
50 GPU_PipelineCacheKeyConverter cvt;
51 cvt.as_uint64 = 0;
52 cvt.as_struct.blend_mode = params->blend_mode;
53 cvt.as_struct.frag_shader = params->frag_shader;
54 cvt.as_struct.vert_shader = params->vert_shader;
55 cvt.as_struct.attachment_format = params->attachment_format;
56 cvt.as_struct.primitive_type = params->primitive_type;
57
58 // 64-bit uint hash function stolen from taisei (which stole it from somewhere else)
59 Uint64 x = cvt.as_uint64;
60 x = (x ^ (x >> 30)) * UINT64_C(0xbf58476d1ce4e5b9);
61 x = (x ^ (x >> 27)) * UINT64_C(0x94d049bb133111eb);
62 x = x ^ (x >> 31);
63 return (Uint32)(x & 0xffffffff);
64}
65
66static bool SDLCALL MatchPipelineCacheKey(void *userdata, const void *a, const void *b)
67{
68 return (SDL_memcmp(a, b, sizeof (GPU_PipelineParameters)) == 0);
69}
70
71static void SDLCALL DestroyPipelineCacheHashItem(void *userdata, const void *key, const void *value)
72{
73 SDL_GPUGraphicsPipeline *pipeline = (SDL_GPUGraphicsPipeline *) value;
74 SDL_GPUDevice *device = (SDL_GPUDevice *) userdata;
75 SDL_ReleaseGPUGraphicsPipeline(device, pipeline);
76 SDL_free((GPU_PipelineParameters *) key);
77}
78
79bool GPU_InitPipelineCache(GPU_PipelineCache *cache, SDL_GPUDevice *device)
80{
81 cache->table = SDL_CreateHashTable(0, false, HashPipelineCacheKey, MatchPipelineCacheKey, DestroyPipelineCacheHashItem, device);
82 return (cache->table != NULL);
83}
84
85void GPU_DestroyPipelineCache(GPU_PipelineCache *cache)
86{
87 SDL_DestroyHashTable(cache->table);
88}
89
90static SDL_GPUGraphicsPipeline *MakePipeline(SDL_GPUDevice *device, GPU_Shaders *shaders, const GPU_PipelineParameters *params)
91{
92 SDL_GPUColorTargetDescription ad;
93 SDL_zero(ad);
94 ad.format = params->attachment_format;
95
96 SDL_BlendMode blend = params->blend_mode;
97 ad.blend_state.enable_blend = blend != 0;
98 ad.blend_state.color_write_mask = 0xF;
99 ad.blend_state.alpha_blend_op = GPU_ConvertBlendOperation(SDL_GetBlendModeAlphaOperation(blend));
100 ad.blend_state.dst_alpha_blendfactor = GPU_ConvertBlendFactor(SDL_GetBlendModeDstAlphaFactor(blend));
101 ad.blend_state.src_alpha_blendfactor = GPU_ConvertBlendFactor(SDL_GetBlendModeSrcAlphaFactor(blend));
102 ad.blend_state.color_blend_op = GPU_ConvertBlendOperation(SDL_GetBlendModeColorOperation(blend));
103 ad.blend_state.dst_color_blendfactor = GPU_ConvertBlendFactor(SDL_GetBlendModeDstColorFactor(blend));
104 ad.blend_state.src_color_blendfactor = GPU_ConvertBlendFactor(SDL_GetBlendModeSrcColorFactor(blend));
105
106 SDL_GPUGraphicsPipelineCreateInfo pci;
107 SDL_zero(pci);
108 pci.target_info.has_depth_stencil_target = false;
109 pci.target_info.num_color_targets = 1;
110 pci.target_info.color_target_descriptions = &ad;
111 pci.vertex_shader = GPU_GetVertexShader(shaders, params->vert_shader);
112 pci.fragment_shader = GPU_GetFragmentShader(shaders, params->frag_shader);
113 pci.multisample_state.sample_count = SDL_GPU_SAMPLECOUNT_1;
114 pci.multisample_state.enable_mask = false;
115 pci.primitive_type = params->primitive_type;
116
117 pci.rasterizer_state.cull_mode = SDL_GPU_CULLMODE_NONE;
118 pci.rasterizer_state.fill_mode = SDL_GPU_FILLMODE_FILL;
119 pci.rasterizer_state.front_face = SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE;
120
121 SDL_GPUVertexBufferDescription vertex_buffer_desc;
122 SDL_zero(vertex_buffer_desc);
123
124 Uint32 num_attribs = 0;
125 SDL_GPUVertexAttribute attribs[4];
126 SDL_zero(attribs);
127
128 bool have_attr_color = false;
129 bool have_attr_uv = false;
130
131 switch (params->vert_shader) {
132 case VERT_SHADER_TRI_TEXTURE:
133 have_attr_uv = true;
134 SDL_FALLTHROUGH;
135 case VERT_SHADER_TRI_COLOR:
136 have_attr_color = true;
137 SDL_FALLTHROUGH;
138 default:
139 break;
140 }
141
142 // Position
143 attribs[num_attribs].location = num_attribs;
144 attribs[num_attribs].format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2;
145 attribs[num_attribs].offset = vertex_buffer_desc.pitch;
146 vertex_buffer_desc.pitch += 2 * sizeof(float);
147 num_attribs++;
148
149 if (have_attr_color) {
150 // Color
151 attribs[num_attribs].location = num_attribs;
152 attribs[num_attribs].format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT4;
153 attribs[num_attribs].offset = vertex_buffer_desc.pitch;
154 vertex_buffer_desc.pitch += 4 * sizeof(float);
155 num_attribs++;
156 }
157
158 if (have_attr_uv) {
159 // UVs
160 attribs[num_attribs].location = num_attribs;
161 attribs[num_attribs].format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2;
162 attribs[num_attribs].offset = vertex_buffer_desc.pitch;
163 vertex_buffer_desc.pitch += 2 * sizeof(float);
164 num_attribs++;
165 }
166
167 pci.vertex_input_state.num_vertex_attributes = num_attribs;
168 pci.vertex_input_state.vertex_attributes = attribs;
169 pci.vertex_input_state.num_vertex_buffers = 1;
170 pci.vertex_input_state.vertex_buffer_descriptions = &vertex_buffer_desc;
171
172 return SDL_CreateGPUGraphicsPipeline(device, &pci);
173}
174
175SDL_GPUGraphicsPipeline *GPU_GetPipeline(GPU_PipelineCache *cache, GPU_Shaders *shaders, SDL_GPUDevice *device, const GPU_PipelineParameters *params)
176{
177 SDL_GPUGraphicsPipeline *pipeline = NULL;
178 if (!SDL_FindInHashTable(cache->table, params, (const void **) &pipeline)) {
179 bool inserted = false;
180 // !!! FIXME: why don't we have an SDL_alloc_copy function/macro?
181 GPU_PipelineParameters *paramscpy = (GPU_PipelineParameters *) SDL_malloc(sizeof (*paramscpy));
182 if (paramscpy) {
183 SDL_copyp(paramscpy, params);
184 pipeline = MakePipeline(device, shaders, params);
185 if (pipeline) {
186 inserted = SDL_InsertIntoHashTable(cache->table, paramscpy, pipeline, false);
187 }
188 }
189
190 if (!inserted) {
191 SDL_free(paramscpy);
192 if (pipeline) {
193 SDL_ReleaseGPUGraphicsPipeline(device, pipeline);
194 pipeline = NULL;
195 }
196 }
197 }
198
199 return pipeline;
200}
201
202#endif // SDL_VIDEO_RENDER_GPU