102 Patches: Detours to the Rescue
C reference for DttR maintainers and modders.
Loading...
Searching...
No Matches
backend_sdl3gpu_resources.c
Go to the documentation of this file.
2#include "graphics_private.h"
3
4#include <dttr_log.h>
5
6#include <string.h>
7
8// Creates persistent vertex and transfer buffers used by per-frame uploads.
10 const uint32_t frame_buffer_size = DTTR_MAX_FRAME_VERTICES * DTTR_VERTEX_SIZE;
11 const SDL_GPUBufferCreateInfo vbuf_info = {
12 .usage = SDL_GPU_BUFFERUSAGE_VERTEX,
13 .size = frame_buffer_size,
14 };
15
16 state->vertex_buffer = SDL_CreateGPUBuffer(state->device, &vbuf_info);
17
18 const SDL_GPUTransferBufferCreateInfo tbuf_info = {
19 .usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD,
20 .size = frame_buffer_size,
21 };
22
23 state->transfer_buffer = SDL_CreateGPUTransferBuffer(state->device, &tbuf_info);
24}
25
26// Creates all sampler variants for wrap/clamp combinations.
28 for (int cu = 0; cu < 2; cu++) {
29 for (int cv = 0; cv < 2; cv++) {
30 const SDL_GPUSamplerCreateInfo si = {
31 .min_filter = SDL_GPU_FILTER_LINEAR,
32 .mag_filter = SDL_GPU_FILTER_LINEAR,
33 .mipmap_mode = SDL_GPU_SAMPLERMIPMAPMODE_LINEAR,
34 .address_mode_u = cu ? SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE
35 : SDL_GPU_SAMPLERADDRESSMODE_REPEAT,
36 .address_mode_v = cv ? SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE
37 : SDL_GPU_SAMPLERADDRESSMODE_REPEAT,
38 .enable_anisotropy = true,
39 .max_anisotropy = DTTR_MAX_ANISOTROPY,
40 };
41
42 state->samplers[cu * 2 + cv] = SDL_CreateGPUSampler(state->device, &si);
43 }
44 }
45}
46
47// Creates render-target and depth textures for the current render resolution.
49 const SDL_GPUTextureFormat swapchain_fmt = SDL_GetGPUSwapchainTextureFormat(
50 state->device,
51 state->window
52 );
53 const SDL_GPUSampleCount sample_count = state->msaa_sample_count;
54
55 const SDL_GPUTextureCreateInfo rt_info = {
56 .type = SDL_GPU_TEXTURETYPE_2D,
57 .format = swapchain_fmt,
58 .usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET | SDL_GPU_TEXTUREUSAGE_SAMPLER,
59 .width = state->width,
60 .height = state->height,
61 .layer_count_or_depth = 1,
62 .num_levels = 1,
63 .sample_count = SDL_GPU_SAMPLECOUNT_1,
64 };
65
66 state->render_target = SDL_CreateGPUTexture(state->device, &rt_info);
67
68 state->msaa_render_target = NULL;
69
70 if (sample_count != SDL_GPU_SAMPLECOUNT_1) {
71 const SDL_GPUTextureCreateInfo msaa_rt_info = {
72 .type = SDL_GPU_TEXTURETYPE_2D,
73 .format = swapchain_fmt,
74 .usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET,
75 .width = state->width,
76 .height = state->height,
77 .layer_count_or_depth = 1,
78 .num_levels = 1,
79 .sample_count = sample_count,
80 };
81
82 state->msaa_render_target = SDL_CreateGPUTexture(state->device, &msaa_rt_info);
83 }
84
85 const SDL_GPUTextureCreateInfo depth_tex_info = {
86 .type = SDL_GPU_TEXTURETYPE_2D,
87 .format = SDL_GPU_TEXTUREFORMAT_D32_FLOAT,
88 .usage = SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET,
89 .width = state->width,
90 .height = state->height,
91 .layer_count_or_depth = 1,
92 .num_levels = 1,
93 .sample_count = sample_count,
94 };
95
96 state->depth_texture = SDL_CreateGPUTexture(state->device, &depth_tex_info);
97}
98
99// Creates the fallback 1x1 texture used when no texture is bound.
101 const SDL_GPUTextureCreateInfo dummy_tex_info = {
102 .type = SDL_GPU_TEXTURETYPE_2D,
103 .format = SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM,
104 .usage = SDL_GPU_TEXTUREUSAGE_SAMPLER,
105 .width = 1,
106 .height = 1,
107 .layer_count_or_depth = 1,
108 .num_levels = 1,
109 };
110
111 state->dummy_texture = SDL_CreateGPUTexture(state->device, &dummy_tex_info);
112}
113
114// Uploads a single white pixel directly into the dummy texture.
116 const uint32_t white_pixel = 0xFFFFFFFF;
117 const uint32_t buf_size = sizeof(white_pixel);
118
119 const SDL_GPUTransferBufferCreateInfo tbuf_info = {
120 .usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD,
121 .size = buf_size,
122 };
123
124 SDL_GPUTransferBuffer *tbuf = SDL_CreateGPUTransferBuffer(state->device, &tbuf_info);
125
126 if (!tbuf) {
127 return;
128 }
129
130 void *mapped = SDL_MapGPUTransferBuffer(state->device, tbuf, false);
131
132 if (!mapped) {
133 SDL_ReleaseGPUTransferBuffer(state->device, tbuf);
134 return;
135 }
136
137 memcpy(mapped, &white_pixel, buf_size);
138 SDL_UnmapGPUTransferBuffer(state->device, tbuf);
139
140 SDL_GPUCommandBuffer *cmd = SDL_AcquireGPUCommandBuffer(state->device);
141
142 if (!cmd) {
143 SDL_ReleaseGPUTransferBuffer(state->device, tbuf);
144 return;
145 }
146
147 SDL_GPUCopyPass *copy = SDL_BeginGPUCopyPass(cmd);
148
149 if (copy) {
150 const SDL_GPUTextureTransferInfo src = {
151 .transfer_buffer = tbuf,
152 .pixels_per_row = 1,
153 };
154
155 const SDL_GPUTextureRegion dst = {
156 .texture = state->dummy_texture,
157 .w = 1,
158 .h = 1,
159 .d = 1,
160 };
161
162 SDL_UploadToGPUTexture(copy, &src, &dst, false);
163 SDL_EndGPUCopyPass(copy);
164 }
165
166 SDL_SubmitGPUCommandBuffer(cmd);
167 SDL_ReleaseGPUTransferBuffer(state->device, tbuf);
168}
169
170// Creates persistent GPU buffers, samplers, and textures required for rendering.
173 const bool needs_msaa_target = state->msaa_sample_count != SDL_GPU_SAMPLECOUNT_1;
174
179
180 if (!state->vertex_buffer || !state->transfer_buffer) {
181 DTTR_LOG_ERROR("Failed to create frame buffers");
182 return false;
183 }
184
185 for (int i = 0; i < DTTR_SAMPLER_COUNT; i++) {
186 if (state->samplers[i]) {
187 continue;
188 }
189
190 DTTR_LOG_ERROR("Failed to create samplers");
191 return false;
192 }
193
194 if (!state->render_target || !state->depth_texture) {
195 DTTR_LOG_ERROR("Failed to create render textures");
196 return false;
197 }
198
199 if (!state->dummy_texture) {
200 DTTR_LOG_ERROR("Failed to create dummy texture");
201 return false;
202 }
203
204 if (needs_msaa_target && !state->msaa_render_target) {
205 DTTR_LOG_ERROR("Failed to create MSAA render target");
206 return false;
207 }
208
210 return true;
211}
212
213// Recreates render-target and depth textures to match a new resolution.
216 const bool needs_msaa_target = state->msaa_sample_count != SDL_GPU_SAMPLECOUNT_1;
217
218 if (!state->device || !state->window || width <= 0 || height <= 0) {
219 return false;
220 }
221
222 if (state->render_target) {
223 SDL_ReleaseGPUTexture(state->device, state->render_target);
224 state->render_target = NULL;
225 }
226
227 if (state->msaa_render_target) {
228 SDL_ReleaseGPUTexture(state->device, state->msaa_render_target);
229 state->msaa_render_target = NULL;
230 }
231
232 if (state->depth_texture) {
233 SDL_ReleaseGPUTexture(state->device, state->depth_texture);
234 state->depth_texture = NULL;
235 }
236
237 state->width = width;
238 state->height = height;
240
241 if (!state->render_target || !state->depth_texture) {
242 DTTR_LOG_ERROR("Failed to recreate render textures at %dx%d", width, height);
243 return false;
244 }
245
246 if (needs_msaa_target && !state->msaa_render_target) {
247 DTTR_LOG_ERROR("Failed to recreate MSAA render target at %dx%d", width, height);
248 return false;
249 }
250
251 return true;
252}
static void upload_dummy_white_pixel(DTTR_BackendState *state)
bool dttr_graphics_sdl3gpu_resize_render_textures(int width, int height)
Recreates resolution-dependent render textures after updating target size.
bool dttr_graphics_sdl3gpu_create_resources()
Creates shared GPU resources used by the SDL3 GPU backend.
static void create_samplers(DTTR_BackendState *state)
static void create_dummy_texture(DTTR_BackendState *state)
static void create_frame_buffers(DTTR_BackendState *state)
static void create_render_textures(DTTR_BackendState *state)
const DTTR_BackendState * state
DTTR_Graphics_COM_Direct3DDevice7 DWORD block DTTR_Graphics_COM_Direct3DDevice7 DWORD block DTTR_Graphics_COM_Direct3DDevice7 void * dst
const uint8_t * src
DTTR_Graphics_COM_DirectDrawSurface7 DWORD flags void NULL
#define DTTR_LOG_ERROR(...)
Definition dttr_log.h:31
#define DTTR_MAX_FRAME_VERTICES
#define DTTR_SAMPLER_COUNT
#define DTTR_MAX_ANISOTROPY
#define DTTR_VERTEX_SIZE
DTTR_BackendState dttr_backend
Definition util.c:8