102 Patches: Detours to the Rescue
C reference for DttR maintainers and modders.
Loading...
Searching...
No Matches
backend_sdl3gpu_pipelines.c
Go to the documentation of this file.
2#include "graphics_private.h"
3
4#include <dttr_log.h>
5
6#include <stddef.h>
7
8#include "gen/sdl3gpu_shaders.h"
9
10// Holds shader bytecode pointer/size pairs for SDL pipeline creation.
11typedef struct {
12 const Uint8 *code;
13 size_t size;
15
16// Returns a readable shader-stage name for diagnostics.
17static const char *shader_stage_name(SDL_GPUShaderStage stage) {
18 switch (stage) {
19 case SDL_GPU_SHADERSTAGE_VERTEX:
20 return "vertex";
21 case SDL_GPU_SHADERSTAGE_FRAGMENT:
22 return "fragment";
23 default:
24 return "compute";
25 }
26}
27
28// Returns the embedded basic vertex shader blob for the selected format.
29static graphics_shader_blob get_basic_vert_blob(SDL_GPUShaderFormat format) {
30 switch (format) {
31 case SDL_GPU_SHADERFORMAT_SPIRV:
32 return (graphics_shader_blob){basic_vert_spv, (size_t)basic_vert_spv_len};
33 case SDL_GPU_SHADERFORMAT_DXIL:
34 return (graphics_shader_blob){basic_vert_dxil, (size_t)basic_vert_dxil_len};
35 default:
36 return (graphics_shader_blob){NULL, 0};
37 }
38}
39
40// Returns the embedded basic fragment shader blob for the selected format.
41static graphics_shader_blob get_basic_frag_blob(SDL_GPUShaderFormat format) {
42 switch (format) {
43 case SDL_GPU_SHADERFORMAT_SPIRV:
44 return (graphics_shader_blob){basic_frag_spv, (size_t)basic_frag_spv_len};
45 case SDL_GPU_SHADERFORMAT_DXIL:
46 return (graphics_shader_blob){basic_frag_dxil, (size_t)basic_frag_dxil_len};
47 default:
48 return (graphics_shader_blob){NULL, 0};
49 }
50}
51
52// Creates one graphics shader object from an embedded blob.
53static SDL_GPUShader *create_shader(
54 const graphics_shader_blob *blob,
55 SDL_GPUShaderStage stage,
56 uint32_t num_samplers
57) {
59
60 if (!blob || !blob->code || blob->size == 0) {
61 SDL_SetError(
62 "No precompiled %s shader blob for %s format",
65 );
66 return NULL;
67 }
68
69 const SDL_GPUShaderCreateInfo info = {
70 .code = blob->code,
71 .code_size = blob->size,
72 .entrypoint = "main",
73 .format = state->shader_format,
74 .stage = stage,
75 .num_samplers = num_samplers,
76 .num_uniform_buffers = 1,
77 };
78
79 return SDL_CreateGPUShader(state->device, &info);
80}
81
82// Releases a temporary vertex/fragment shader pair after pipeline creation.
85 SDL_GPUShader *vert,
86 SDL_GPUShader *frag
87) {
88 if (vert) {
89 SDL_ReleaseGPUShader(state->device, vert);
90 }
91
92 if (frag) {
93 SDL_ReleaseGPUShader(state->device, frag);
94 }
95}
96
97// Builds all blend/depth graphics pipeline variants used by draw replay.
100 SDL_GPUShader *vert,
101 SDL_GPUShader *frag
102) {
103 const SDL_GPUVertexBufferDescription vbuf_desc = {
104 .slot = 0,
105 .pitch = DTTR_VERTEX_SIZE,
106 .input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX,
107 };
108
109 const SDL_GPUVertexAttribute attrs[] = {
110 {0, 0, SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3, 0}, // position
111 {1, 0, SDL_GPU_VERTEXELEMENTFORMAT_FLOAT, offsetof(DTTR_Vertex, rhw)}, // rhw
112 {2, 0, SDL_GPU_VERTEXELEMENTFORMAT_FLOAT4, offsetof(DTTR_Vertex, r)}, // color
113 {3, 0, SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2, offsetof(DTTR_Vertex, u)}, // texcoord
114 };
115
116 const SDL_GPUTextureFormat swapchain_fmt = SDL_GetGPUSwapchainTextureFormat(
117 state->device,
118 state->window
119 );
120
121 const SDL_GPUColorTargetDescription color_targets[3] = {
122 {.format = swapchain_fmt, .blend_state = {.enable_blend = false}},
123 {.format = swapchain_fmt,
124 .blend_state =
125 {
126 .enable_blend = true,
127 .src_color_blendfactor = SDL_GPU_BLENDFACTOR_SRC_ALPHA,
128 .dst_color_blendfactor = SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
129 .color_blend_op = SDL_GPU_BLENDOP_ADD,
130 .src_alpha_blendfactor = SDL_GPU_BLENDFACTOR_ONE,
131 .dst_alpha_blendfactor = SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
132 .alpha_blend_op = SDL_GPU_BLENDOP_ADD,
133 }},
134 {.format = swapchain_fmt,
135 .blend_state = {
136 .enable_blend = true,
137 .src_color_blendfactor = SDL_GPU_BLENDFACTOR_SRC_ALPHA,
138 .dst_color_blendfactor = SDL_GPU_BLENDFACTOR_ONE,
139 .color_blend_op = SDL_GPU_BLENDOP_ADD,
140 .src_alpha_blendfactor = SDL_GPU_BLENDFACTOR_ONE,
141 .dst_alpha_blendfactor = SDL_GPU_BLENDFACTOR_ONE,
142 .alpha_blend_op = SDL_GPU_BLENDOP_ADD,
143 }},
144 };
145
146 for (int bmode = 0; bmode < 3; bmode++) {
147 for (int dtest = 0; dtest < 2; dtest++) {
148 for (int dwrite = 0; dwrite < 2; dwrite++) {
149 const SDL_GPUGraphicsPipelineCreateInfo pipe_info = {
150 .vertex_shader = vert,
151 .fragment_shader = frag,
152 .vertex_input_state =
153 {
154 .vertex_buffer_descriptions = &vbuf_desc,
155 .num_vertex_buffers = 1,
156 .vertex_attributes = attrs,
157 .num_vertex_attributes = DTTR_VERTEX_ATTRIBUTE_COUNT,
158 },
159 .primitive_type = SDL_GPU_PRIMITIVETYPE_TRIANGLELIST,
160 .rasterizer_state =
161 {
162 .fill_mode = SDL_GPU_FILLMODE_FILL,
163 .cull_mode = SDL_GPU_CULLMODE_NONE,
164 .front_face = SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE,
165 },
166 .multisample_state =
167 {
168 .sample_count = state->msaa_sample_count,
169 .sample_mask = 0,
170 .enable_mask = false,
171 },
172 .depth_stencil_state =
173 {
174 .enable_depth_test = dtest,
175 .enable_depth_write = dwrite,
176 .compare_op = dtest ? SDL_GPU_COMPAREOP_LESS_OR_EQUAL
177 : SDL_GPU_COMPAREOP_ALWAYS,
178 },
179 .target_info = {
180 .color_target_descriptions = &color_targets[bmode],
181 .num_color_targets = 1,
182 .has_depth_stencil_target = true,
183 .depth_stencil_format = SDL_GPU_TEXTUREFORMAT_D32_FLOAT,
184 },
185 };
186
187 const int idx = DTTR_PIPELINE_INDEX(bmode, dtest, dwrite);
188 state->pipelines[idx] = SDL_CreateGPUGraphicsPipeline(
189 state->device,
190 &pipe_info
191 );
192
193 if (state->pipelines[idx]) {
194 continue;
195 }
196
197 DTTR_LOG_ERROR("Failed to create pipeline[%d]: %s", idx, SDL_GetError());
198 return false;
199 }
200 }
201 }
202
203 return true;
204}
205
206// Creates all graphics pipelines required by the backend.
209
210 const graphics_shader_blob vert_blob = get_basic_vert_blob(state->shader_format);
211 SDL_GPUShader *vert = create_shader(&vert_blob, SDL_GPU_SHADERSTAGE_VERTEX, 0);
212
213 if (!vert) {
214 DTTR_LOG_ERROR("Failed to create vertex shader: %s", SDL_GetError());
215 return false;
216 }
217
218 const graphics_shader_blob frag_blob = get_basic_frag_blob(state->shader_format);
219
220 SDL_GPUShader *frag = create_shader(&frag_blob, SDL_GPU_SHADERSTAGE_FRAGMENT, 1);
221
222 if (!frag) {
223 DTTR_LOG_ERROR("Failed to create fragment shader: %s", SDL_GetError());
225 return false;
226 }
227
228 if (!create_graphics_pipelines(state, vert, frag)) {
229 release_shader_pair(state, vert, frag);
230 return false;
231 }
232
233 release_shader_pair(state, vert, frag);
234 return true;
235}
static SDL_GPUShader * create_shader(const graphics_shader_blob *blob, SDL_GPUShaderStage stage, uint32_t num_samplers)
static graphics_shader_blob get_basic_frag_blob(SDL_GPUShaderFormat format)
static bool create_graphics_pipelines(DTTR_BackendState *state, SDL_GPUShader *vert, SDL_GPUShader *frag)
static void release_shader_pair(DTTR_BackendState *state, SDL_GPUShader *vert, SDL_GPUShader *frag)
bool dttr_graphics_sdl3gpu_create_pipelines()
Builds all graphics pipelines used by the SDL3 GPU backend.
static graphics_shader_blob get_basic_vert_blob(SDL_GPUShaderFormat format)
static const char * shader_stage_name(SDL_GPUShaderStage stage)
DTTR_Graphics_COM_Direct3DDevice7 void *status DTTR_Graphics_COM_Direct3DDevice7 DWORD DWORD void DWORD DWORD f DTTR_Graphics_COM_Direct3DDevice7 DWORD void DWORD DWORD DWORD f DTTR_Graphics_COM_Direct3DDevice7 void float * r
const DTTR_BackendState * state
DTTR_Graphics_COM_Direct3DDevice7 void *status DTTR_Graphics_COM_Direct3DDevice7 DWORD DWORD void DWORD DWORD f DTTR_Graphics_COM_Direct3DDevice7 DWORD void DWORD DWORD DWORD f DTTR_Graphics_COM_Direct3DDevice7 void float DWORD DWORD f DWORD stage
DTTR_Graphics_COM_DirectDrawSurface7 DWORD flags void NULL
#define DTTR_LOG_ERROR(...)
Definition dttr_log.h:31
#define DTTR_VERTEX_ATTRIBUTE_COUNT
#define DTTR_VERTEX_SIZE
DTTR_BackendState dttr_backend
Definition util.c:8
#define DTTR_PIPELINE_INDEX(bmode, dtest, dwrite)
const char * dttr_graphics_shader_format_name(SDL_GPUShaderFormat format)
Definition util.c:121