v / thirdparty / sokol / sokol_gfx.h
19478 lines · 17762 sloc · 850.69 KB · 125c899d62b4a0a5791b37f644ebd19543cb4e55
Raw
1#if defined(SOKOL_IMPL) && !defined(SOKOL_GFX_IMPL)
2#define SOKOL_GFX_IMPL
3#endif
4#ifndef SOKOL_GFX_INCLUDED
5/*
6 sokol_gfx.h -- simple 3D API wrapper
7
8 Project URL: https://github.com/floooh/sokol
9
10 Example code: https://github.com/floooh/sokol-samples
11
12 Do this:
13 #define SOKOL_IMPL or
14 #define SOKOL_GFX_IMPL
15 before you include this file in *one* C or C++ file to create the
16 implementation.
17
18 In the same place define one of the following to select the rendering
19 backend:
20 #define SOKOL_GLCORE
21 #define SOKOL_GLES3
22 #define SOKOL_D3D11
23 #define SOKOL_METAL
24 #define SOKOL_WGPU
25 #define SOKOL_DUMMY_BACKEND
26
27 I.e. for the desktop GL it should look like this:
28
29 #include ...
30 #include ...
31 #define SOKOL_IMPL
32 #define SOKOL_GLCORE
33 #include "sokol_gfx.h"
34
35 The dummy backend replaces the platform-specific backend code with empty
36 stub functions. This is useful for writing tests that need to run on the
37 command line.
38
39 Optionally provide the following defines with your own implementations:
40
41 SOKOL_ASSERT(c) - your own assert macro (default: assert(c))
42 SOKOL_UNREACHABLE() - a guard macro for unreachable code (default: assert(false))
43 SOKOL_GFX_API_DECL - public function declaration prefix (default: extern)
44 SOKOL_API_DECL - same as SOKOL_GFX_API_DECL
45 SOKOL_API_IMPL - public function implementation prefix (default: -)
46 SOKOL_TRACE_HOOKS - enable trace hook callbacks (search below for TRACE HOOKS)
47 SOKOL_EXTERNAL_GL_LOADER - indicates that you're using your own GL loader, in this case
48 sokol_gfx.h will not include any platform GL headers and disable
49 the integrated Win32 GL loader
50
51 If sokol_gfx.h is compiled as a DLL, define the following before
52 including the declaration or implementation:
53
54 SOKOL_DLL
55
56 On Windows, SOKOL_DLL will define SOKOL_GFX_API_DECL as __declspec(dllexport)
57 or __declspec(dllimport) as needed.
58
59 If you want to compile without deprecated structs and functions,
60 define:
61
62 SOKOL_NO_DEPRECATED
63
64 Optionally define the following to force debug checks and validations
65 even in release mode:
66
67 SOKOL_DEBUG - by default this is defined if _DEBUG is defined
68
69 sokol_gfx DOES NOT:
70 ===================
71 - create a window, swapchain or the 3D-API context/device, you must do this
72 before sokol_gfx is initialized, and pass any required information
73 (like 3D device pointers) to the sokol_gfx initialization call
74
75 - present the rendered frame, how this is done exactly usually depends
76 on how the window and 3D-API context/device was created
77
78 - provide a unified shader language, instead 3D-API-specific shader
79 source-code or shader-bytecode must be provided (for the "official"
80 offline shader cross-compiler, see here:
81 https://github.com/floooh/sokol-tools/blob/master/docs/sokol-shdc.md)
82
83
84 STEP BY STEP
85 ============
86 --- to initialize sokol_gfx, after creating a window and a 3D-API
87 context/device, call:
88
89 sg_setup(const sg_desc*)
90
91 Depending on the selected 3D backend, sokol-gfx requires some
92 information, like a device pointer, default swapchain pixel formats
93 and so on. If you are using sokol_app.h for the window system
94 glue, you can use a helper function provided in the sokol_glue.h
95 header:
96
97 #include "sokol_gfx.h"
98 #include "sokol_app.h"
99 #include "sokol_glue.h"
100 //...
101 sg_setup(&(sg_desc){
102 .environment = sglue_environment(),
103 });
104
105 To get any logging output for errors and from the validation layer, you
106 need to provide a logging callback. Easiest way is through sokol_log.h:
107
108 #include "sokol_log.h"
109 //...
110 sg_setup(&(sg_desc){
111 //...
112 .logger.func = slog_func,
113 });
114
115 --- create resource objects (at least buffers, shaders and pipelines,
116 and optionally images, samplers and render-pass-attachments):
117
118 sg_buffer sg_make_buffer(const sg_buffer_desc*)
119 sg_image sg_make_image(const sg_image_desc*)
120 sg_sampler sg_make_sampler(const sg_sampler_desc*)
121 sg_shader sg_make_shader(const sg_shader_desc*)
122 sg_pipeline sg_make_pipeline(const sg_pipeline_desc*)
123 sg_attachments sg_make_attachments(const sg_attachments_desc*)
124
125 --- start a render pass:
126
127 sg_begin_pass(const sg_pass* pass);
128
129 Typically, passes render into an externally provided swapchain which
130 presents the rendering result on the display. Such a 'swapchain pass'
131 is started like this:
132
133 sg_begin_pass(&(sg_pass){ .action = { ... }, .swapchain = sglue_swapchain() })
134
135 ...where .action is an sg_pass_action struct containing actions to be performed
136 at the start and end of a render pass (such as clearing the render surfaces to
137 a specific color), and .swapchain is an sg_swapchain
138 struct all the required information to render into the swapchain's surfaces.
139
140 To start an 'offscreen pass' into sokol-gfx image objects, an sg_attachment
141 object handle is required instead of an sg_swapchain struct. An offscreen
142 pass is started like this (assuming attachments is an sg_attachments handle):
143
144 sg_begin_pass(&(sg_pass){ .action = { ... }, .attachments = attachments });
145
146 --- set the render pipeline state for the next draw call with:
147
148 sg_apply_pipeline(sg_pipeline pip)
149
150 --- fill an sg_bindings struct with the resource bindings for the next
151 draw call (0..N vertex buffers, 0 or 1 index buffer, 0..N image-objects,
152 samplers and storage-buffers), and call:
153
154 sg_apply_bindings(const sg_bindings* bindings)
155
156 to update the resource bindings
157
158 --- optionally update shader uniform data with:
159
160 sg_apply_uniforms(sg_shader_stage stage, int ub_index, const sg_range* data)
161
162 Read the section 'UNIFORM DATA LAYOUT' to learn about the expected memory layout
163 of the uniform data passed into sg_apply_uniforms().
164
165 --- kick off a draw call with:
166
167 sg_draw(int base_element, int num_elements, int num_instances)
168
169 The sg_draw() function unifies all the different ways to render primitives
170 in a single call (indexed vs non-indexed rendering, and instanced vs non-instanced
171 rendering). In case of indexed rendering, base_element and num_element specify
172 indices in the currently bound index buffer. In case of non-indexed rendering
173 base_element and num_elements specify vertices in the currently bound
174 vertex-buffer(s). To perform instanced rendering, the rendering pipeline
175 must be setup for instancing (see sg_pipeline_desc below), a separate vertex buffer
176 containing per-instance data must be bound, and the num_instances parameter
177 must be > 1.
178
179 --- finish the current rendering pass with:
180
181 sg_end_pass()
182
183 --- when done with the current frame, call
184
185 sg_commit()
186
187 --- at the end of your program, shutdown sokol_gfx with:
188
189 sg_shutdown()
190
191 --- if you need to destroy resources before sg_shutdown(), call:
192
193 sg_destroy_buffer(sg_buffer buf)
194 sg_destroy_image(sg_image img)
195 sg_destroy_sampler(sg_sampler smp)
196 sg_destroy_shader(sg_shader shd)
197 sg_destroy_pipeline(sg_pipeline pip)
198 sg_destroy_attachments(sg_attachments atts)
199
200 --- to set a new viewport rectangle, call
201
202 sg_apply_viewport(int x, int y, int width, int height, bool origin_top_left)
203
204 ...or if you want to specify the viewport rectangle with float values:
205
206 sg_apply_viewportf(float x, float y, float width, float height, bool origin_top_left)
207
208 --- to set a new scissor rect, call:
209
210 sg_apply_scissor_rect(int x, int y, int width, int height, bool origin_top_left)
211
212 ...or with float values:
213
214 sg_apply_scissor_rectf(float x, float y, float width, float height, bool origin_top_left)
215
216 Both sg_apply_viewport() and sg_apply_scissor_rect() must be called
217 inside a rendering pass
218
219 Note that sg_begin_default_pass() and sg_begin_pass() will reset both the
220 viewport and scissor rectangles to cover the entire framebuffer.
221
222 --- to update (overwrite) the content of buffer and image resources, call:
223
224 sg_update_buffer(sg_buffer buf, const sg_range* data)
225 sg_update_image(sg_image img, const sg_image_data* data)
226
227 Buffers and images to be updated must have been created with
228 SG_USAGE_DYNAMIC or SG_USAGE_STREAM
229
230 Only one update per frame is allowed for buffer and image resources when
231 using the sg_update_*() functions. The rationale is to have a simple
232 countermeasure to avoid the CPU scribbling over data the GPU is currently
233 using, or the CPU having to wait for the GPU
234
235 Buffer and image updates can be partial, as long as a rendering
236 operation only references the valid (updated) data in the
237 buffer or image.
238
239 --- to append a chunk of data to a buffer resource, call:
240
241 int sg_append_buffer(sg_buffer buf, const sg_range* data)
242
243 The difference to sg_update_buffer() is that sg_append_buffer()
244 can be called multiple times per frame to append new data to the
245 buffer piece by piece, optionally interleaved with draw calls referencing
246 the previously written data.
247
248 sg_append_buffer() returns a byte offset to the start of the
249 written data, this offset can be assigned to
250 sg_bindings.vertex_buffer_offsets[n] or
251 sg_bindings.index_buffer_offset
252
253 Code example:
254
255 for (...) {
256 const void* data = ...;
257 const int num_bytes = ...;
258 int offset = sg_append_buffer(buf, &(sg_range) { .ptr=data, .size=num_bytes });
259 bindings.vertex_buffer_offsets[0] = offset;
260 sg_apply_pipeline(pip);
261 sg_apply_bindings(&bindings);
262 sg_apply_uniforms(...);
263 sg_draw(...);
264 }
265
266 A buffer to be used with sg_append_buffer() must have been created
267 with SG_USAGE_DYNAMIC or SG_USAGE_STREAM.
268
269 If the application appends more data to the buffer then fits into
270 the buffer, the buffer will go into the "overflow" state for the
271 rest of the frame.
272
273 Any draw calls attempting to render an overflown buffer will be
274 silently dropped (in debug mode this will also result in a
275 validation error).
276
277 You can also check manually if a buffer is in overflow-state by calling
278
279 bool sg_query_buffer_overflow(sg_buffer buf)
280
281 You can manually check to see if an overflow would occur before adding
282 any data to a buffer by calling
283
284 bool sg_query_buffer_will_overflow(sg_buffer buf, size_t size)
285
286 NOTE: Due to restrictions in underlying 3D-APIs, appended chunks of
287 data will be 4-byte aligned in the destination buffer. This means
288 that there will be gaps in index buffers containing 16-bit indices
289 when the number of indices in a call to sg_append_buffer() is
290 odd. This isn't a problem when each call to sg_append_buffer()
291 is associated with one draw call, but will be problematic when
292 a single indexed draw call spans several appended chunks of indices.
293
294 --- to check at runtime for optional features, limits and pixelformat support,
295 call:
296
297 sg_features sg_query_features()
298 sg_limits sg_query_limits()
299 sg_pixelformat_info sg_query_pixelformat(sg_pixel_format fmt)
300
301 --- if you need to call into the underlying 3D-API directly, you must call:
302
303 sg_reset_state_cache()
304
305 ...before calling sokol_gfx functions again
306
307 --- you can inspect the original sg_desc structure handed to sg_setup()
308 by calling sg_query_desc(). This will return an sg_desc struct with
309 the default values patched in instead of any zero-initialized values
310
311 --- you can get a desc struct matching the creation attributes of a
312 specific resource object via:
313
314 sg_buffer_desc sg_query_buffer_desc(sg_buffer buf)
315 sg_image_desc sg_query_image_desc(sg_image img)
316 sg_sampler_desc sg_query_sampler_desc(sg_sampler smp)
317 sg_shader_desc sq_query_shader_desc(sg_shader shd)
318 sg_pipeline_desc sg_query_pipeline_desc(sg_pipeline pip)
319 sg_attachments_desc sg_query_attachments_desc(sg_attachments atts)
320
321 ...but NOTE that the returned desc structs may be incomplete, only
322 creation attributes that are kept around internally after resource
323 creation will be filled in, and in some cases (like shaders) that's
324 very little. Any missing attributes will be set to zero. The returned
325 desc structs might still be useful as partial blueprint for creating
326 similar resources if filled up with the missing attributes.
327
328 Calling the query-desc functions on an invalid resource will return
329 completely zeroed structs (it makes sense to check the resource state
330 with sg_query_*_state() first)
331
332 --- you can query the default resource creation parameters through the functions
333
334 sg_buffer_desc sg_query_buffer_defaults(const sg_buffer_desc* desc)
335 sg_image_desc sg_query_image_defaults(const sg_image_desc* desc)
336 sg_sampler_desc sg_query_sampler_defaults(const sg_sampler_desc* desc)
337 sg_shader_desc sg_query_shader_defaults(const sg_shader_desc* desc)
338 sg_pipeline_desc sg_query_pipeline_defaults(const sg_pipeline_desc* desc)
339 sg_attachments_desc sg_query_attachments_defaults(const sg_attachments_desc* desc)
340
341 These functions take a pointer to a desc structure which may contain
342 zero-initialized items for default values. These zero-init values
343 will be replaced with their concrete values in the returned desc
344 struct.
345
346 --- you can inspect various internal resource runtime values via:
347
348 sg_buffer_info sg_query_buffer_info(sg_buffer buf)
349 sg_image_info sg_query_image_info(sg_image img)
350 sg_sampler_info sg_query_sampler_info(sg_sampler smp)
351 sg_shader_info sg_query_shader_info(sg_shader shd)
352 sg_pipeline_info sg_query_pipeline_info(sg_pipeline pip)
353 sg_attachments_info sg_query_attachments_info(sg_attachments atts)
354
355 ...please note that the returned info-structs are tied quite closely
356 to sokol_gfx.h internals, and may change more often than other
357 public API functions and structs.
358
359 --- you can query frame stats and control stats collection via:
360
361 sg_query_frame_stats()
362 sg_enable_frame_stats()
363 sg_disable_frame_stats()
364 sg_frame_stats_enabled()
365
366 --- you can ask at runtime what backend sokol_gfx.h has been compiled for:
367
368 sg_backend sg_query_backend(void)
369
370 --- call the following helper functions to compute the number of
371 bytes in a texture row or surface for a specific pixel format.
372 These functions might be helpful when preparing image data for consumption
373 by sg_make_image() or sg_update_image():
374
375 int sg_query_row_pitch(sg_pixel_format fmt, int width, int int row_align_bytes);
376 int sg_query_surface_pitch(sg_pixel_format fmt, int width, int height, int row_align_bytes);
377
378 Width and height are generally in number pixels, but note that 'row' has different meaning
379 for uncompressed vs compressed pixel formats: for uncompressed formats, a row is identical
380 with a single line if pixels, while in compressed formats, one row is a line of *compression blocks*.
381
382 This is why calling sg_query_surface_pitch() for a compressed pixel format and height
383 N, N+1, N+2, ... may return the same result.
384
385 The row_align_bytes parammeter is for added flexibility. For image data that goes into
386 the sg_make_image() or sg_update_image() this should generally be 1, because these
387 functions take tightly packed image data as input no matter what alignment restrictions
388 exist in the backend 3D APIs.
389
390 ON INITIALIZATION:
391 ==================
392 When calling sg_setup(), a pointer to an sg_desc struct must be provided
393 which contains initialization options. These options provide two types
394 of information to sokol-gfx:
395
396 (1) upper bounds and limits needed to allocate various internal
397 data structures:
398 - the max number of resources of each type that can
399 be alive at the same time, this is used for allocating
400 internal pools
401 - the max overall size of uniform data that can be
402 updated per frame, including a worst-case alignment
403 per uniform update (this worst-case alignment is 256 bytes)
404 - the max size of all dynamic resource updates (sg_update_buffer,
405 sg_append_buffer and sg_update_image) per frame
406 Not all of those limit values are used by all backends, but it is
407 good practice to provide them none-the-less.
408
409 (2) 3D backend "environment information" in a nested sg_environment struct:
410 - pointers to backend-specific context- or device-objects (for instance
411 the D3D11, WebGPU or Metal device objects)
412 - defaults for external swapchain pixel formats and sample counts,
413 these will be used as default values in image and pipeline objects,
414 and the sg_swapchain struct passed into sg_begin_pass()
415 Usually you provide a complete sg_environment struct through
416 a helper function, as an example look at the sglue_environment()
417 function in the sokol_glue.h header.
418
419 See the documentation block of the sg_desc struct below for more information.
420
421
422 ON RENDER PASSES
423 ================
424 Relevant samples:
425 - https://floooh.github.io/sokol-html5/offscreen-sapp.html
426 - https://floooh.github.io/sokol-html5/offscreen-msaa-sapp.html
427 - https://floooh.github.io/sokol-html5/mrt-sapp.html
428 - https://floooh.github.io/sokol-html5/mrt-pixelformats-sapp.html
429
430 A render pass groups rendering commands into a set of render target images
431 (called 'pass attachments'). Render target images can be used in subsequent
432 passes as textures (it is invalid to use the same image both as render target
433 and as texture in the same pass).
434
435 The following sokol-gfx functions must only be called inside a render pass:
436
437 sg_apply_viewport(f)
438 sg_apply_scissor_rect(f)
439 sg_apply_pipeline
440 sg_apply_bindings
441 sg_apply_uniforms
442 sg_draw
443
444 A frame must have at least one 'swapchain render pass' which renders into an
445 externally provided swapchain provided as an sg_swapchain struct to the
446 sg_begin_pass() function. The sg_swapchain struct must contain the
447 following information:
448
449 - the color pixel-format of the swapchain's render surface
450 - an optional depth/stencil pixel format if the swapchain
451 has a depth/stencil buffer
452 - an optional sample-count for MSAA rendering
453 - NOTE: the above three values can be zero-initialized, in that
454 case the defaults from the sg_environment struct will be used that
455 had been passed to the sg_setup() function.
456 - a number of backend specific objects:
457 - GL/GLES3: just a GL framebuffer handle
458 - D3D11:
459 - an ID3D11RenderTargetView for the rendering surface
460 - if MSAA is used, an ID3D11RenderTargetView as
461 MSAA resolve-target
462 - an optional ID3D11DepthStencilView for the
463 depth/stencil buffer
464 - WebGPU
465 - a WGPUTextureView object for the rendering surface
466 - if MSAA is used, a WGPUTextureView object as MSAA resolve target
467 - an optional WGPUTextureView for the
468 - Metal (NOTE that the roles of provided surfaces is slightly
469 different in Metal than in D3D11 or WebGPU, notably, the
470 CAMetalDrawable is either rendered to directly, or serves
471 as MSAA resolve target):
472 - a CAMetalDrawable object which is either rendered
473 into directly, or in case of MSAA rendering, serves
474 as MSAA-resolve-target
475 - if MSAA is used, an multisampled MTLTexture where
476 rendering goes into
477 - an optional MTLTexture for the depth/stencil buffer
478
479 It's recommended that you create a helper function which returns an
480 initialized sg_swapchain struct by value. This can then be directly plugged
481 into the sg_begin_pass function like this:
482
483 sg_begin_pass(&(sg_pass){ .swapchain = sglue_swapchain() });
484
485 As an example for such a helper function check out the function sglue_swapchain()
486 in the sokol_glue.h header.
487
488 For offscreen render passes, the render target images used in a render pass
489 are baked into an immutable sg_attachments object.
490
491 For a simple offscreen scenario with one color-, one depth-stencil-render
492 target and without multisampling, creating an attachment object looks like this:
493
494 First create two render target images, one with a color pixel format,
495 and one with the depth- or depth-stencil pixel format. Both images
496 must have the same dimensions:
497
498 const sg_image color_img = sg_make_image(&(sg_image_desc){
499 .render_target = true,
500 .width = 256,
501 .height = 256,
502 .pixel_format = SG_PIXELFORMAT_RGBA8,
503 .sample_count = 1,
504 });
505 const sg_image depth_img = sg_make_image(&(sg_image_desc){
506 .render_target = true,
507 .width = 256,
508 .height = 256,
509 .pixel_format = SG_PIXELFORMAT_DEPTH,
510 .sample_count = 1,
511 });
512
513 NOTE: when creating render target images, have in mind that some default values
514 are aligned with the default environment attributes in the sg_environment struct
515 that was passed into the sg_setup() call:
516
517 - the default value for sg_image_desc.pixel_format is taken from
518 sg_environment.defaults.color_format
519 - the default value for sg_image_desc.sample_count is taken from
520 sg_environment.defaults.sample_count
521 - the default value for sg_image_desc.num_mipmaps is always 1
522
523 Next create an attachments object:
524
525 const sg_attachments atts = sg_make_attachments(&(sg_attachments_desc){
526 .colors[0].image = color_img,
527 .depth_stencil.image = depth_img,
528 });
529
530 This attachments object is then passed into the sg_begin_pass() function
531 in place of the swapchain struct:
532
533 sg_begin_pass(&(sg_pass){ .attachments = atts });
534
535 Swapchain and offscreen passes form dependency trees each with a swapchain
536 pass at the root, offscreen passes as nodes, and render target images as
537 dependencies between passes.
538
539 sg_pass_action structs are used to define actions that should happen at the
540 start and end of rendering passes (such as clearing pass attachments to a
541 specific color or depth-value, or performing an MSAA resolve operation at
542 the end of a pass).
543
544 A typical sg_pass_action object which clears the color attachment to black
545 might look like this:
546
547 const sg_pass_action = {
548 .colors[0] = {
549 .load_action = SG_LOADACTION_CLEAR,
550 .clear_value = { 0.0f, 0.0f, 0.0f, 1.0f }
551 }
552 };
553
554 This omits the defaults for the color attachment store action, and
555 the depth-stencil-attachments actions. The same pass action with the
556 defaults explicitly filled in would look like this:
557
558 const sg_pass_action pass_action = {
559 .colors[0] = {
560 .load_action = SG_LOADACTION_CLEAR,
561 .store_action = SG_STOREACTION_STORE,
562 .clear_value = { 0.0f, 0.0f, 0.0f, 1.0f }
563 },
564 .depth = = {
565 .load_action = SG_LOADACTION_CLEAR,
566 .store_action = SG_STOREACTION_DONTCARE,
567 .clear_value = 1.0f,
568 },
569 .stencil = {
570 .load_action = SG_LOADACTION_CLEAR,
571 .store_action = SG_STOREACTION_DONTCARE,
572 .clear_value = 0
573 }
574 };
575
576 With the sg_pass object and sg_pass_action struct in place everything
577 is ready now for the actual render pass:
578
579 Using such this prepared sg_pass_action in a swapchain pass looks like
580 this:
581
582 sg_begin_pass(&(sg_pass){
583 .action = pass_action,
584 .swapchain = sglue_swapchain()
585 });
586 ...
587 sg_end_pass();
588
589 ...of alternatively in one offscreen pass:
590
591 sg_begin_pass(&(sg_pass){
592 .action = pass_action,
593 .attachments = attachments,
594 });
595 ...
596 sg_end_pass();
597
598 Offscreen rendering can also go into a mipmap, or a slice/face of
599 a cube-, array- or 3d-image (which some restrictions, for instance
600 it's not possible to create a 3D image with a depth/stencil pixel format,
601 these exceptions are generally caught by the sokol-gfx validation layer).
602
603 The mipmap/slice selection happens at attachments creation time, for instance
604 to render into mipmap 2 of slice 3 of an array texture:
605
606 const sg_attachments atts = sg_make_attachments(&(sg_attachments_desc){
607 .colors[0] = {
608 .image = color_img,
609 .mip_level = 2,
610 .slice = 3,
611 },
612 .depth_stencil.image = depth_img,
613 });
614
615 If MSAA offscreen rendering is desired, the multi-sample rendering result
616 must be 'resolved' into a separate 'resolve image', before that image can
617 be used as texture.
618
619 NOTE: currently multisample-images cannot be bound as textures.
620
621 Creating a simple attachments object for multisampled rendering requires
622 3 attachment images: the color attachment image which has a sample
623 count > 1, a resolve attachment image of the same size and pixel format
624 but a sample count == 1, and a depth/stencil attachment image with
625 the same size and sample count as the color attachment image:
626
627 const sg_image color_img = sg_make_image(&(sg_image_desc){
628 .render_target = true,
629 .width = 256,
630 .height = 256,
631 .pixel_format = SG_PIXELFORMAT_RGBA8,
632 .sample_count = 4,
633 });
634 const sg_image resolve_img = sg_make_image(&(sg_image_desc){
635 .render_target = true,
636 .width = 256,
637 .height = 256,
638 .pixel_format = SG_PIXELFORMAT_RGBA8,
639 .sample_count = 1,
640 });
641 const sg_image depth_img = sg_make_image(&(sg_image_desc){
642 .render_target = true,
643 .width = 256,
644 .height = 256,
645 .pixel_format = SG_PIXELFORMAT_DEPTH,
646 .sample_count = 4,
647 });
648
649 ...create the attachments object:
650
651 const sg_attachments atts = sg_make_attachments(&(sg_attachments_desc){
652 .colors[0].image = color_img,
653 .resolves[0].image = resolve_img,
654 .depth_stencil.image = depth_img,
655 });
656
657 If an attachments object defines a resolve image in a specific resolve attachment slot,
658 an 'msaa resolve operation' will happen in sg_end_pass().
659
660 In this scenario, the content of the MSAA color attachment doesn't need to be
661 preserved (since it's only needed inside sg_end_pass for the msaa-resolve), so
662 the .store_action should be set to "don't care":
663
664 const sg_pass_action = {
665 .colors[0] = {
666 .load_action = SG_LOADACTION_CLEAR,
667 .store_action = SG_STOREACTION_DONTCARE,
668 .clear_value = { 0.0f, 0.0f, 0.0f, 1.0f }
669 }
670 };
671
672 The actual render pass looks as usual:
673
674 sg_begin_pass(&(sg_pass){ .action = pass_action, .attachments = atts });
675 ...
676 sg_end_pass();
677
678 ...after sg_end_pass() the only difference to the non-msaa scenario is that the
679 rendering result which is going to be used as texture in a followup pass is
680 in 'resolve_img', not in 'color_img' (in fact, trying to bind color_img as a
681 texture would result in a validation error).
682
683
684 ON SHADER CREATION
685 ==================
686 sokol-gfx doesn't come with an integrated shader cross-compiler, instead
687 backend-specific shader sources or binary blobs need to be provided when
688 creating a shader object, along with information about the shader resource
689 binding interface needed in the sokol-gfx validation layer and to properly
690 bind shader resources on the CPU-side to be consumable by the GPU-side.
691
692 The easiest way to provide all this shader creation data is to use the
693 sokol-shdc shader compiler tool to compile shaders from a common
694 GLSL syntax into backend-specific sources or binary blobs, along with
695 shader interface information and uniform blocks mapped to C structs.
696
697 To create a shader using a C header which has been code-generated by sokol-shdc:
698
699 // include the C header code-generated by sokol-shdc:
700 #include "myshader.glsl.h"
701 ...
702
703 // create shader using a code-generated helper function from the C header:
704 sg_shader shd = sg_make_shader(myshader_shader_desc(sg_query_backend()));
705
706 The samples in the 'sapp' subdirectory of the sokol-samples project
707 also use the sokol-shdc approach:
708
709 https://github.com/floooh/sokol-samples/tree/master/sapp
710
711 If you're planning to use sokol-shdc, you can stop reading here, instead
712 continue with the sokol-shdc documentation:
713
714 https://github.com/floooh/sokol-tools/blob/master/docs/sokol-shdc.md
715
716 To create shaders with backend-specific shader code or binary blobs,
717 the sg_make_shader() function requires the following information:
718
719 - Shader code or shader binary blobs for the vertex- and fragment- shader-stage:
720 - for the desktop GL backend, source code can be provided in '#version 410' or
721 '#version 430', version 430 is required for storage buffer support, but note
722 that this is not available on macOS
723 - for the GLES3 backend, source code must be provided in '#version 300 es' syntax
724 - for the D3D11 backend, shaders can be provided as source or binary blobs, the
725 source code should be in HLSL4.0 (for best compatibility) or alternatively
726 in HLSL5.0 syntax (other versions may work but are not tested), NOTE: when
727 shader source code is provided for the D3D11 backend, sokol-gfx will dynamically
728 load 'd3dcompiler_47.dll'
729 - for the Metal backends, shaders can be provided as source or binary blobs, the
730 MSL version should be in 'metal-1.1' (other versions may work but are not tested)
731 - for the WebGPU backend, shader must be provided as WGSL source code
732 - optionally the following shader-code related attributes can be provided:
733 - an entry function name (only on D3D11 or Metal, but not OpenGL)
734 - on D3D11 only, a compilation target (default is "vs_4_0" and "ps_4_0")
735
736 - Depending on backend, information about the input vertex attributes used by the
737 vertex shader:
738 - Metal: no information needed since vertex attributes are always bound
739 by their attribute location defined in the shader via '[[attribute(N)]]'
740 - WebGPU: no information needed since vertex attributes are always
741 bound by their attribute location defined in the shader via `@location(N)`
742 - GLSL: vertex attribute names can be optionally provided, in that case their
743 location will be looked up by name, otherwise, the vertex attribute location
744 can be defined with 'layout(location = N)', PLEASE NOTE that the name-lookup method
745 may be removed at some point
746 - D3D11: a 'semantic name' and 'semantic index' must be provided for each vertex
747 attribute, e.g. if the vertex attribute is defined as 'TEXCOORD1' in the shader,
748 the semantic name would be 'TEXCOORD', and the semantic index would be '1'
749
750 - Information about each uniform block used in the shader:
751 - The size of the uniform block in number of bytes.
752 - A memory layout hint (currently 'native' or 'std140') where 'native' defines a
753 backend-specific memory layout which shouldn't be used for cross-platform code.
754 Only std140 guarantees a backend-agnostic memory layout.
755 - For GLSL only: a description of the internal uniform block layout, which maps
756 member types and their offsets on the CPU side to uniform variable names
757 in the GLSL shader
758 - please also NOTE the documentation sections about UNIFORM DATA LAYOUT
759 and CROSS-BACKEND COMMON UNIFORM DATA LAYOUT below!
760
761 - A description of each storage buffer used in the shader:
762 - a boolean 'readonly' flag, note that currently only
763 readonly storage buffers are supported
764 - note that storage buffers are not supported on all backends
765 and platforms
766
767 - A description of each texture/image used in the shader:
768 - the expected image type:
769 - SG_IMAGETYPE_2D
770 - SG_IMAGETYPE_CUBE
771 - SG_IMAGETYPE_3D
772 - SG_IMAGETYPE_ARRAY
773 - the expected 'image sample type':
774 - SG_IMAGESAMPLETYPE_FLOAT
775 - SG_IMAGESAMPLETYPE_DEPTH
776 - SG_IMAGESAMPLETYPE_SINT
777 - SG_IMAGESAMPLETYPE_UINT
778 - SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT
779 - a flag whether the texture is expected to be multisampled
780 (currently it's not supported to fetch data from multisampled
781 textures in shaders, but this is planned for a later time)
782
783 - A description of each texture sampler used in the shader:
784 - SG_SAMPLERTYPE_FILTERING,
785 - SG_SAMPLERTYPE_NONFILTERING,
786 - SG_SAMPLERTYPE_COMPARISON,
787
788 - An array of 'image-sampler-pairs' used by the shader to sample textures,
789 for D3D11, Metal and WebGPU this is used for validation purposes to check
790 whether the texture and sampler are compatible with each other (especially
791 WebGPU is very picky about combining the correct
792 texture-sample-type with the correct sampler-type). For GLSL an
793 additional 'combined-image-sampler name' must be provided because 'OpenGL
794 style GLSL' cannot handle separate texture and sampler objects, but still
795 groups them into a traditional GLSL 'sampler object'.
796
797 Compatibility rules for image-sample-type vs sampler-type are as follows:
798
799 - SG_IMAGESAMPLETYPE_FLOAT => (SG_SAMPLERTYPE_FILTERING or SG_SAMPLERTYPE_NONFILTERING)
800 - SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT => SG_SAMPLERTYPE_NONFILTERING
801 - SG_IMAGESAMPLETYPE_SINT => SG_SAMPLERTYPE_NONFILTERING
802 - SG_IMAGESAMPLETYPE_UINT => SG_SAMPLERTYPE_NONFILTERING
803 - SG_IMAGESAMPLETYPE_DEPTH => SG_SAMPLERTYPE_COMPARISON
804
805 For example code of how to create backend-specific shader objects,
806 please refer to the following samples:
807
808 - for D3D11: https://github.com/floooh/sokol-samples/tree/master/d3d11
809 - for Metal: https://github.com/floooh/sokol-samples/tree/master/metal
810 - for OpenGL: https://github.com/floooh/sokol-samples/tree/master/glfw
811 - for GLES3: https://github.com/floooh/sokol-samples/tree/master/html5
812 - for WebGPI: https://github.com/floooh/sokol-samples/tree/master/wgpu
813
814
815 ON SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT AND SG_SAMPLERTYPE_NONFILTERING
816 ========================================================================
817 The WebGPU backend introduces the concept of 'unfilterable-float' textures,
818 which can only be combined with 'nonfiltering' samplers (this is a restriction
819 specific to WebGPU, but since the same sokol-gfx code should work across
820 all backend, the sokol-gfx validation layer also enforces this restriction
821 - the alternative would be undefined behaviour in some backend APIs on
822 some devices).
823
824 The background is that some mobile devices (most notably iOS devices) can
825 not perform linear filtering when sampling textures with certain pixel
826 formats, most notable the 32F formats:
827
828 - SG_PIXELFORMAT_R32F
829 - SG_PIXELFORMAT_RG32F
830 - SG_PIXELFORMAT_RGBA32F
831
832 The information of whether a shader is going to be used with such an
833 unfilterable-float texture must already be provided in the sg_shader_desc
834 struct when creating the shader (see the above section "ON SHADER CREATION").
835
836 If you are using the sokol-shdc shader compiler, the information whether a
837 texture/sampler binding expects an 'unfilterable-float/nonfiltering'
838 texture/sampler combination cannot be inferred from the shader source
839 alone, you'll need to provide this hint via annotation-tags. For instance
840 here is an example from the ozz-skin-sapp.c sample shader which samples an
841 RGBA32F texture with skinning matrices in the vertex shader:
842
843 ```glsl
844 @image_sample_type joint_tex unfilterable_float
845 uniform texture2D joint_tex;
846 @sampler_type smp nonfiltering
847 uniform sampler smp;
848 ```
849
850 This will result in SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT and
851 SG_SAMPLERTYPE_NONFILTERING being written to the code-generated
852 sg_shader_desc struct.
853
854
855 UNIFORM DATA LAYOUT:
856 ====================
857 NOTE: if you use the sokol-shdc shader compiler tool, you don't need to worry
858 about the following details.
859
860 The data that's passed into the sg_apply_uniforms() function must adhere to
861 specific layout rules so that the GPU shader finds the uniform block
862 items at the right offset.
863
864 For the D3D11 and Metal backends, sokol-gfx only cares about the size of uniform
865 blocks, but not about the internal layout. The data will just be copied into
866 a uniform/constant buffer in a single operation and it's up you to arrange the
867 CPU-side layout so that it matches the GPU side layout. This also means that with
868 the D3D11 and Metal backends you are not limited to a 'cross-platform' subset
869 of uniform variable types.
870
871 If you ever only use one of the D3D11, Metal *or* WebGPU backend, you can stop reading here.
872
873 For the GL backends, the internal layout of uniform blocks matters though,
874 and you are limited to a small number of uniform variable types. This is
875 because sokol-gfx must be able to locate the uniform block members in order
876 to upload them to the GPU with glUniformXXX() calls.
877
878 To describe the uniform block layout to sokol-gfx, the following information
879 must be passed to the sg_make_shader() call in the sg_shader_desc struct:
880
881 - a hint about the used packing rule (either SG_UNIFORMLAYOUT_NATIVE or
882 SG_UNIFORMLAYOUT_STD140)
883 - a list of the uniform block members types in the correct order they
884 appear on the CPU side
885
886 For example if the GLSL shader has the following uniform declarations:
887
888 uniform mat4 mvp;
889 uniform vec2 offset0;
890 uniform vec2 offset1;
891 uniform vec2 offset2;
892
893 ...and on the CPU side, there's a similar C struct:
894
895 typedef struct {
896 float mvp[16];
897 float offset0[2];
898 float offset1[2];
899 float offset2[2];
900 } params_t;
901
902 ...the uniform block description in the sg_shader_desc must look like this:
903
904 sg_shader_desc desc = {
905 .vs.uniform_blocks[0] = {
906 .size = sizeof(params_t),
907 .layout = SG_UNIFORMLAYOUT_NATIVE, // this is the default and can be omitted
908 .uniforms = {
909 // order must be the same as in 'params_t':
910 [0] = { .name = "mvp", .type = SG_UNIFORMTYPE_MAT4 },
911 [1] = { .name = "offset0", .type = SG_UNIFORMTYPE_VEC2 },
912 [2] = { .name = "offset1", .type = SG_UNIFORMTYPE_VEC2 },
913 [3] = { .name = "offset2", .type = SG_UNIFORMTYPE_VEC2 },
914 }
915 }
916 };
917
918 With this information sokol-gfx can now compute the correct offsets of the data items
919 within the uniform block struct.
920
921 The SG_UNIFORMLAYOUT_NATIVE packing rule works fine if only the GL backends are used,
922 but for proper D3D11/Metal/GL a subset of the std140 layout must be used which is
923 described in the next section:
924
925
926 CROSS-BACKEND COMMON UNIFORM DATA LAYOUT
927 ========================================
928 For cross-platform / cross-3D-backend code it is important that the same uniform block
929 layout on the CPU side can be used for all sokol-gfx backends. To achieve this,
930 a common subset of the std140 layout must be used:
931
932 - The uniform block layout hint in sg_shader_desc must be explicitly set to
933 SG_UNIFORMLAYOUT_STD140.
934 - Only the following GLSL uniform types can be used (with their associated sokol-gfx enums):
935 - float => SG_UNIFORMTYPE_FLOAT
936 - vec2 => SG_UNIFORMTYPE_FLOAT2
937 - vec3 => SG_UNIFORMTYPE_FLOAT3
938 - vec4 => SG_UNIFORMTYPE_FLOAT4
939 - int => SG_UNIFORMTYPE_INT
940 - ivec2 => SG_UNIFORMTYPE_INT2
941 - ivec3 => SG_UNIFORMTYPE_INT3
942 - ivec4 => SG_UNIFORMTYPE_INT4
943 - mat4 => SG_UNIFORMTYPE_MAT4
944 - Alignment for those types must be as follows (in bytes):
945 - float => 4
946 - vec2 => 8
947 - vec3 => 16
948 - vec4 => 16
949 - int => 4
950 - ivec2 => 8
951 - ivec3 => 16
952 - ivec4 => 16
953 - mat4 => 16
954 - Arrays are only allowed for the following types: vec4, int4, mat4.
955
956 Note that the HLSL cbuffer layout rules are slightly different from the
957 std140 layout rules, this means that the cbuffer declarations in HLSL code
958 must be tweaked so that the layout is compatible with std140.
959
960 The by far easiest way to tackle the common uniform block layout problem is
961 to use the sokol-shdc shader cross-compiler tool!
962
963 ON STORAGE BUFFERS
964 ==================
965 Storage buffers can be used to pass large amounts of random access structured
966 data fromt the CPU side to the shaders. They are similar to data textures, but are
967 more convenient to use both on the CPU and shader side since they can be accessed
968 in shaders as as a 1-dimensional array of struct items.
969
970 Storage buffers are *NOT* supported on the following platform/backend combos:
971
972 - macOS+GL (because storage buffers require GL 4.3, while macOS only goes up to GL 4.1)
973 - all GLES3 platforms (WebGL2, iOS, Android - with the option that support on
974 Android may be added at a later point)
975
976 Currently only 'readonly' storage buffers are supported (meaning it's not possible
977 to write to storage buffers from shaders).
978
979 To use storage buffers, the following steps are required:
980
981 - write a shader which uses storage buffers (also see the example links below)
982 - create one or more storage buffers via sg_make_buffer() with the
983 buffer type SG_BUFFERTYPE_STORAGEBUFFER
984 - when creating a shader via sg_make_shader(), populate the sg_shader_desc
985 struct with binding info (when using sokol-shdc, this step will be taken care
986 of automatically)
987 - which storage buffer bind slots on the vertex- and fragment-stage
988 are occupied
989 - whether the storage buffer on that bind slot is readonly (this is currently required
990 to be true)
991 - when calling sg_apply_bindings(), apply the matching bind slots with the previously
992 created storage buffers
993 - ...and that's it.
994
995 For more details, see the following backend-agnostic sokol samples:
996
997 - simple vertex pulling from a storage buffer:
998 - C code: https://github.com/floooh/sokol-samples/blob/master/sapp/vertexpull-sapp.c
999 - shader: https://github.com/floooh/sokol-samples/blob/master/sapp/vertexpull-sapp.glsl
1000 - instanced rendering via storage buffers (vertex- and instance-pulling):
1001 - C code: https://github.com/floooh/sokol-samples/blob/master/sapp/instancing-pull-sapp.c
1002 - shader: https://github.com/floooh/sokol-samples/blob/master/sapp/instancing-pull-sapp.glsl
1003 - storage buffers both on the vertex- and fragment-stage:
1004 - C code: https://github.com/floooh/sokol-samples/blob/master/sapp/sbuftex-sapp.c
1005 - shader: https://github.com/floooh/sokol-samples/blob/master/sapp/sbuftex-sapp.glsl
1006 - the Ozz animation sample rewritten to pull all rendering data from storage buffers:
1007 - C code: https://github.com/floooh/sokol-samples/blob/master/sapp/ozz-storagebuffer-sapp.cc
1008 - shader: https://github.com/floooh/sokol-samples/blob/master/sapp/ozz-storagebuffer-sapp.glsl
1009
1010 ...also see the following backend-specific vertex pulling samples (those also don't use sokol-shdc):
1011
1012 - D3D11: https://github.com/floooh/sokol-samples/blob/master/d3d11/vertexpulling-d3d11.c
1013 - desktop GL: https://github.com/floooh/sokol-samples/blob/master/glfw/vertexpulling-glfw.c
1014 - Metal: https://github.com/floooh/sokol-samples/blob/master/metal/vertexpulling-metal.c
1015 - WebGPU: https://github.com/floooh/sokol-samples/blob/master/wgpu/vertexpulling-wgpu.c
1016
1017 Storage buffer shader authoring caveats when using sokol-shdc:
1018
1019 - declare a storage buffer interface block with `readonly buffer [name] { ... }`
1020 - do NOT annotate storage buffers with `layout(...)`, sokol-shdc will take care of that
1021 - declare a struct which describes a single array item in the storage buffer interface block
1022 - only put a single flexible array member into the storage buffer interface block
1023
1024 E.g. a complete example in 'sokol-shdc GLSL':
1025
1026 ```glsl
1027 // declare a struct:
1028 struct sb_vertex {
1029 vec3 pos;
1030 vec4 color;
1031 }
1032 // declare a buffer interface block with a single flexible struct array:
1033 readonly buffer vertices {
1034 sb_vertex vtx[];
1035 }
1036 // in the shader function, access the storage buffer like this:
1037 void main() {
1038 vec3 pos = vtx[gl_VertexIndex].pos;
1039 ...
1040 }
1041 ```
1042
1043 Backend-specific storage-buffer caveats (not relevant when using sokol-shdc):
1044
1045 D3D11:
1046 - storage buffers are created as 'raw' Byte Address Buffers
1047 (https://learn.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-resources-intro#raw-views-of-buffers)
1048 - in HLSL, use a ByteAddressBuffer to access the buffer content
1049 (https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-object-byteaddressbuffer)
1050 - in D3D11, storage buffers and textures share the same bind slots, sokol-gfx reserves
1051 shader resource slots 0..15 for textures and 16..23 for storage buffers.
1052 - e.g. in HLSL, storage buffer bindings start at register(t16) no matter the shader stage
1053
1054 Metal:
1055 - in Metal there is no internal difference between vertex-, uniform- and
1056 storage-buffers, all are bound to the same 'buffer bind slots' with the
1057 following reserved ranges:
1058 - vertex shader stage:
1059 - uniform buffers (internal): slots 0..3
1060 - vertex buffers: slots 4..11
1061 - storage buffers: slots 12..19
1062 - fragment shader stage:
1063 - uniform buffers (internal): slots 0..3
1064 - storage buffers: slots 4..11
1065 - this means in MSL, storage buffer bindings start at [[buffer(12)]] in the vertex
1066 shaders, and at [[buffer(4)]] in fragment shaders
1067
1068 GL:
1069 - the GL backend doesn't use name-lookup to find storage buffer bindings, this
1070 means you must annotate buffers with `layout(std430, binding=N)` in GLSL
1071 - ...where N is 0..7 in the vertex shader, and 8..15 in the fragment shader
1072
1073 WebGPU:
1074 - in WGSL, use the following bind locations for the various shader resource types:
1075 - vertex shader stage:
1076 - textures `@group(1) @binding(0..15)`
1077 - samplers `@group(1) @binding(16..31)`
1078 - storage buffers `@group(1) @binding(32..47)`
1079 - fragment shader stage:
1080 - textures `@group(1) @binding(48..63)`
1081 - samplers `@group(1) @binding(64..79)`
1082 - storage buffers `@group(1) @binding(80..95)`
1083
1084 TRACE HOOKS:
1085 ============
1086 sokol_gfx.h optionally allows to install "trace hook" callbacks for
1087 each public API functions. When a public API function is called, and
1088 a trace hook callback has been installed for this function, the
1089 callback will be invoked with the parameters and result of the function.
1090 This is useful for things like debugging- and profiling-tools, or
1091 keeping track of resource creation and destruction.
1092
1093 To use the trace hook feature:
1094
1095 --- Define SOKOL_TRACE_HOOKS before including the implementation.
1096
1097 --- Setup an sg_trace_hooks structure with your callback function
1098 pointers (keep all function pointers you're not interested
1099 in zero-initialized), optionally set the user_data member
1100 in the sg_trace_hooks struct.
1101
1102 --- Install the trace hooks by calling sg_install_trace_hooks(),
1103 the return value of this function is another sg_trace_hooks
1104 struct which contains the previously set of trace hooks.
1105 You should keep this struct around, and call those previous
1106 functions pointers from your own trace callbacks for proper
1107 chaining.
1108
1109 As an example of how trace hooks are used, have a look at the
1110 imgui/sokol_gfx_imgui.h header which implements a realtime
1111 debugging UI for sokol_gfx.h on top of Dear ImGui.
1112
1113
1114 A NOTE ON PORTABLE PACKED VERTEX FORMATS:
1115 =========================================
1116 There are two things to consider when using packed
1117 vertex formats like UBYTE4, SHORT2, etc which need to work
1118 across all backends:
1119
1120 - D3D11 can only convert *normalized* vertex formats to
1121 floating point during vertex fetch, normalized formats
1122 have a trailing 'N', and are "normalized" to a range
1123 -1.0..+1.0 (for the signed formats) or 0.0..1.0 (for the
1124 unsigned formats):
1125
1126 - SG_VERTEXFORMAT_BYTE4N
1127 - SG_VERTEXFORMAT_UBYTE4N
1128 - SG_VERTEXFORMAT_SHORT2N
1129 - SG_VERTEXFORMAT_USHORT2N
1130 - SG_VERTEXFORMAT_SHORT4N
1131 - SG_VERTEXFORMAT_USHORT4N
1132
1133 D3D11 will not convert *non-normalized* vertex formats to floating point
1134 vertex shader inputs, those can only be uses with the *ivecn* vertex shader
1135 input types when D3D11 is used as backend (GL and Metal can use both formats)
1136
1137 - SG_VERTEXFORMAT_BYTE4,
1138 - SG_VERTEXFORMAT_UBYTE4
1139 - SG_VERTEXFORMAT_SHORT2
1140 - SG_VERTEXFORMAT_SHORT4
1141
1142 For a vertex input layout which works on all platforms, only use the following
1143 vertex formats, and if needed "expand" the normalized vertex shader
1144 inputs in the vertex shader by multiplying with 127.0, 255.0, 32767.0 or
1145 65535.0:
1146
1147 - SG_VERTEXFORMAT_FLOAT,
1148 - SG_VERTEXFORMAT_FLOAT2,
1149 - SG_VERTEXFORMAT_FLOAT3,
1150 - SG_VERTEXFORMAT_FLOAT4,
1151 - SG_VERTEXFORMAT_BYTE4N,
1152 - SG_VERTEXFORMAT_UBYTE4N,
1153 - SG_VERTEXFORMAT_SHORT2N,
1154 - SG_VERTEXFORMAT_USHORT2N
1155 - SG_VERTEXFORMAT_SHORT4N,
1156 - SG_VERTEXFORMAT_USHORT4N
1157 - SG_VERTEXFORMAT_UINT10_N2
1158 - SG_VERTEXFORMAT_HALF2
1159 - SG_VERTEXFORMAT_HALF4
1160
1161
1162 MEMORY ALLOCATION OVERRIDE
1163 ==========================
1164 You can override the memory allocation functions at initialization time
1165 like this:
1166
1167 void* my_alloc(size_t size, void* user_data) {
1168 return malloc(size);
1169 }
1170
1171 void my_free(void* ptr, void* user_data) {
1172 free(ptr);
1173 }
1174
1175 ...
1176 sg_setup(&(sg_desc){
1177 // ...
1178 .allocator = {
1179 .alloc_fn = my_alloc,
1180 .free_fn = my_free,
1181 .user_data = ...,
1182 }
1183 });
1184 ...
1185
1186 If no overrides are provided, malloc and free will be used.
1187
1188 This only affects memory allocation calls done by sokol_gfx.h
1189 itself though, not any allocations in OS libraries.
1190
1191
1192 ERROR REPORTING AND LOGGING
1193 ===========================
1194 To get any logging information at all you need to provide a logging callback in the setup call
1195 the easiest way is to use sokol_log.h:
1196
1197 #include "sokol_log.h"
1198
1199 sg_setup(&(sg_desc){ .logger.func = slog_func });
1200
1201 To override logging with your own callback, first write a logging function like this:
1202
1203 void my_log(const char* tag, // e.g. 'sg'
1204 uint32_t log_level, // 0=panic, 1=error, 2=warn, 3=info
1205 uint32_t log_item_id, // SG_LOGITEM_*
1206 const char* message_or_null, // a message string, may be nullptr in release mode
1207 uint32_t line_nr, // line number in sokol_gfx.h
1208 const char* filename_or_null, // source filename, may be nullptr in release mode
1209 void* user_data)
1210 {
1211 ...
1212 }
1213
1214 ...and then setup sokol-gfx like this:
1215
1216 sg_setup(&(sg_desc){
1217 .logger = {
1218 .func = my_log,
1219 .user_data = my_user_data,
1220 }
1221 });
1222
1223 The provided logging function must be reentrant (e.g. be callable from
1224 different threads).
1225
1226 If you don't want to provide your own custom logger it is highly recommended to use
1227 the standard logger in sokol_log.h instead, otherwise you won't see any warnings or
1228 errors.
1229
1230
1231 COMMIT LISTENERS
1232 ================
1233 It's possible to hook callback functions into sokol-gfx which are called from
1234 inside sg_commit() in unspecified order. This is mainly useful for libraries
1235 that build on top of sokol_gfx.h to be notified about the end/start of a frame.
1236
1237 To add a commit listener, call:
1238
1239 static void my_commit_listener(void* user_data) {
1240 ...
1241 }
1242
1243 bool success = sg_add_commit_listener((sg_commit_listener){
1244 .func = my_commit_listener,
1245 .user_data = ...,
1246 });
1247
1248 The function returns false if the internal array of commit listeners is full,
1249 or the same commit listener had already been added.
1250
1251 If the function returns true, my_commit_listener() will be called each frame
1252 from inside sg_commit().
1253
1254 By default, 1024 distinct commit listeners can be added, but this number
1255 can be tweaked in the sg_setup() call:
1256
1257 sg_setup(&(sg_desc){
1258 .max_commit_listeners = 2048,
1259 });
1260
1261 An sg_commit_listener item is equal to another if both the function
1262 pointer and user_data field are equal.
1263
1264 To remove a commit listener:
1265
1266 bool success = sg_remove_commit_listener((sg_commit_listener){
1267 .func = my_commit_listener,
1268 .user_data = ...,
1269 });
1270
1271 ...where the .func and .user_data field are equal to a previous
1272 sg_add_commit_listener() call. The function returns true if the commit
1273 listener item was found and removed, and false otherwise.
1274
1275
1276 RESOURCE CREATION AND DESTRUCTION IN DETAIL
1277 ===========================================
1278 The 'vanilla' way to create resource objects is with the 'make functions':
1279
1280 sg_buffer sg_make_buffer(const sg_buffer_desc* desc)
1281 sg_image sg_make_image(const sg_image_desc* desc)
1282 sg_sampler sg_make_sampler(const sg_sampler_desc* desc)
1283 sg_shader sg_make_shader(const sg_shader_desc* desc)
1284 sg_pipeline sg_make_pipeline(const sg_pipeline_desc* desc)
1285 sg_attachments sg_make_attachments(const sg_attachments_desc* desc)
1286
1287 This will result in one of three cases:
1288
1289 1. The returned handle is invalid. This happens when there are no more
1290 free slots in the resource pool for this resource type. An invalid
1291 handle is associated with the INVALID resource state, for instance:
1292
1293 sg_buffer buf = sg_make_buffer(...)
1294 if (sg_query_buffer_state(buf) == SG_RESOURCESTATE_INVALID) {
1295 // buffer pool is exhausted
1296 }
1297
1298 2. The returned handle is valid, but creating the underlying resource
1299 has failed for some reason. This results in a resource object in the
1300 FAILED state. The reason *why* resource creation has failed differ
1301 by resource type. Look for log messages with more details. A failed
1302 resource state can be checked with:
1303
1304 sg_buffer buf = sg_make_buffer(...)
1305 if (sg_query_buffer_state(buf) == SG_RESOURCESTATE_FAILED) {
1306 // creating the resource has failed
1307 }
1308
1309 3. And finally, if everything goes right, the returned resource is
1310 in resource state VALID and ready to use. This can be checked
1311 with:
1312
1313 sg_buffer buf = sg_make_buffer(...)
1314 if (sg_query_buffer_state(buf) == SG_RESOURCESTATE_VALID) {
1315 // creating the resource has failed
1316 }
1317
1318 When calling the 'make functions', the created resource goes through a number
1319 of states:
1320
1321 - INITIAL: the resource slot associated with the new resource is currently
1322 free (technically, there is no resource yet, just an empty pool slot)
1323 - ALLOC: a handle for the new resource has been allocated, this just means
1324 a pool slot has been reserved.
1325 - VALID or FAILED: in VALID state any 3D API backend resource objects have
1326 been successfully created, otherwise if anything went wrong, the resource
1327 will be in FAILED state.
1328
1329 Sometimes it makes sense to first grab a handle, but initialize the
1330 underlying resource at a later time. For instance when loading data
1331 asynchronously from a slow data source, you may know what buffers and
1332 textures are needed at an early stage of the loading process, but actually
1333 loading the buffer or texture content can only be completed at a later time.
1334
1335 For such situations, sokol-gfx resource objects can be created in two steps.
1336 You can allocate a handle upfront with one of the 'alloc functions':
1337
1338 sg_buffer sg_alloc_buffer(void)
1339 sg_image sg_alloc_image(void)
1340 sg_sampler sg_alloc_sampler(void)
1341 sg_shader sg_alloc_shader(void)
1342 sg_pipeline sg_alloc_pipeline(void)
1343 sg_attachments sg_alloc_attachments(void)
1344
1345 This will return a handle with the underlying resource object in the
1346 ALLOC state:
1347
1348 sg_image img = sg_alloc_image();
1349 if (sg_query_image_state(img) == SG_RESOURCESTATE_ALLOC) {
1350 // allocating an image handle has succeeded, otherwise
1351 // the image pool is full
1352 }
1353
1354 Such an 'incomplete' handle can be used in most sokol-gfx rendering functions
1355 without doing any harm, sokol-gfx will simply skip any rendering operation
1356 that involve resources which are not in VALID state.
1357
1358 At a later time (for instance once the texture has completed loading
1359 asynchronously), the resource creation can be completed by calling one of
1360 the 'init functions', those functions take an existing resource handle and
1361 'desc struct':
1362
1363 void sg_init_buffer(sg_buffer buf, const sg_buffer_desc* desc)
1364 void sg_init_image(sg_image img, const sg_image_desc* desc)
1365 void sg_init_sampler(sg_sampler smp, const sg_sampler_desc* desc)
1366 void sg_init_shader(sg_shader shd, const sg_shader_desc* desc)
1367 void sg_init_pipeline(sg_pipeline pip, const sg_pipeline_desc* desc)
1368 void sg_init_attachments(sg_attachments atts, const sg_attachments_desc* desc)
1369
1370 The init functions expect a resource in ALLOC state, and after the function
1371 returns, the resource will be either in VALID or FAILED state. Calling
1372 an 'alloc function' followed by the matching 'init function' is fully
1373 equivalent with calling the 'make function' alone.
1374
1375 Destruction can also happen as a two-step process. The 'uninit functions'
1376 will put a resource object from the VALID or FAILED state back into the
1377 ALLOC state:
1378
1379 void sg_uninit_buffer(sg_buffer buf)
1380 void sg_uninit_image(sg_image img)
1381 void sg_uninit_sampler(sg_sampler smp)
1382 void sg_uninit_shader(sg_shader shd)
1383 void sg_uninit_pipeline(sg_pipeline pip)
1384 void sg_uninit_attachments(sg_attachments pass)
1385
1386 Calling the 'uninit functions' with a resource that is not in the VALID or
1387 FAILED state is a no-op.
1388
1389 To finally free the pool slot for recycling call the 'dealloc functions':
1390
1391 void sg_dealloc_buffer(sg_buffer buf)
1392 void sg_dealloc_image(sg_image img)
1393 void sg_dealloc_sampler(sg_sampler smp)
1394 void sg_dealloc_shader(sg_shader shd)
1395 void sg_dealloc_pipeline(sg_pipeline pip)
1396 void sg_dealloc_attachments(sg_attachments atts)
1397
1398 Calling the 'dealloc functions' on a resource that's not in ALLOC state is
1399 a no-op, but will generate a warning log message.
1400
1401 Calling an 'uninit function' and 'dealloc function' in sequence is equivalent
1402 with calling the associated 'destroy function':
1403
1404 void sg_destroy_buffer(sg_buffer buf)
1405 void sg_destroy_image(sg_image img)
1406 void sg_destroy_sampler(sg_sampler smp)
1407 void sg_destroy_shader(sg_shader shd)
1408 void sg_destroy_pipeline(sg_pipeline pip)
1409 void sg_destroy_attachments(sg_attachments atts)
1410
1411 The 'destroy functions' can be called on resources in any state and generally
1412 do the right thing (for instance if the resource is in ALLOC state, the destroy
1413 function will be equivalent to the 'dealloc function' and skip the 'uninit part').
1414
1415 And finally to close the circle, the 'fail functions' can be called to manually
1416 put a resource in ALLOC state into the FAILED state:
1417
1418 sg_fail_buffer(sg_buffer buf)
1419 sg_fail_image(sg_image img)
1420 sg_fail_sampler(sg_sampler smp)
1421 sg_fail_shader(sg_shader shd)
1422 sg_fail_pipeline(sg_pipeline pip)
1423 sg_fail_attachments(sg_attachments atts)
1424
1425 This is recommended if anything went wrong outside of sokol-gfx during asynchronous
1426 resource setup (for instance a file loading operation failed). In this case,
1427 the 'fail function' should be called instead of the 'init function'.
1428
1429 Calling a 'fail function' on a resource that's not in ALLOC state is a no-op,
1430 but will generate a warning log message.
1431
1432 NOTE: that two-step resource creation usually only makes sense for buffers
1433 and images, but not for samplers, shaders, pipelines or attachments. Most notably, trying
1434 to create a pipeline object with a shader that's not in VALID state will
1435 trigger a validation layer error, or if the validation layer is disabled,
1436 result in a pipeline object in FAILED state. Same when trying to create
1437 an attachments object with invalid image objects.
1438
1439
1440 WEBGPU CAVEATS
1441 ==============
1442 For a general overview and design notes of the WebGPU backend see:
1443
1444 https://floooh.github.io/2023/10/16/sokol-webgpu.html
1445
1446 In general, don't expect an automatic speedup when switching from the WebGL2
1447 backend to the WebGPU backend. Some WebGPU functions currently actually
1448 have a higher CPU overhead than similar WebGL2 functions, leading to the
1449 paradoxical situation that some WebGPU code may be slower than similar WebGL2
1450 code.
1451
1452 - when writing WGSL shader code by hand, a specific bind-slot convention
1453 must be used:
1454
1455 All uniform block structs must use `@group(0)`, with up to
1456 4 uniform blocks per shader stage.
1457 - Vertex shader uniform block bindings must start at `@group(0) @binding(0)`
1458 - Fragment shader uniform blocks bindings must start at `@group(0) @binding(4)`
1459
1460 All textures and samplers must use `@group(1)` and start at specific
1461 offsets depending on resource type and shader stage.
1462 - Vertex shader textures must start at `@group(1) @binding(0)`
1463 - Vertex shader samplers must start at `@group(1) @binding(16)`
1464 - Vertex shader storage buffers must start at `@group(1) @binding(32)`
1465 - Fragment shader textures must start at `@group(1) @binding(48)`
1466 - Fragment shader samplers must start at `@group(1) @binding(64)`
1467 - Fragment shader storage buffers must start at `@group(1) @binding(80)`
1468
1469 Note that the actual number of allowed per-stage texture- and sampler-bindings
1470 in sokol-gfx is currently lower than the above ranges (currently only up to
1471 12 textures, 8 samplers and 8 storage buffers are allowed per shader stage).
1472
1473 If you use sokol-shdc to generate WGSL shader code, you don't need to worry
1474 about the above binding convention since sokol-shdc assigns bind slots
1475 automatically.
1476
1477 - The sokol-gfx WebGPU backend uses the sg_desc.uniform_buffer_size item
1478 to allocate a single per-frame uniform buffer which must be big enough
1479 to hold all data written by sg_apply_uniforms() during a single frame,
1480 including a worst-case 256-byte alignment (e.g. each sg_apply_uniform
1481 call will cost 256 bytes of uniform buffer size). The default size
1482 is 4 MB, which is enough for 16384 sg_apply_uniform() calls per
1483 frame (assuming the uniform data 'payload' is less than 256 bytes
1484 per call). These rules are the same as for the Metal backend, so if
1485 you are already using the Metal backend you'll be fine.
1486
1487 - sg_apply_bindings(): the sokol-gfx WebGPU backend implements a bindgroup
1488 cache to prevent excessive creation and destruction of BindGroup objects
1489 when calling sg_apply_bindings(). The number of slots in the bindgroups
1490 cache is defined in sg_desc.wgpu_bindgroups_cache_size when calling
1491 sg_setup. The cache size must be a power-of-2 number, with the default being
1492 1024. The bindgroups cache behaviour can be observed by calling the new
1493 function sg_query_frame_stats(), where the following struct items are
1494 of interest:
1495
1496 .wgpu.num_bindgroup_cache_hits
1497 .wgpu.num_bindgroup_cache_misses
1498 .wgpu.num_bindgroup_cache_collisions
1499 .wgpu.num_bindgroup_cache_vs_hash_key_mismatch
1500
1501 The value to pay attention to is `.wgpu.num_bindgroup_cache_collisions`,
1502 if this number if consistently higher than a few percent of the
1503 .wgpu.num_set_bindgroup value, it might be a good idea to bump the
1504 bindgroups cache size to the next power-of-2.
1505
1506 - sg_apply_viewport(): WebGPU currently has a unique restriction that viewport
1507 rectangles must be contained entirely within the framebuffer. As a shitty
1508 workaround sokol_gfx.h will clip incoming viewport rectangles against
1509 the framebuffer, but this will distort the clipspace-to-screenspace mapping.
1510 There's no proper way to handle this inside sokol_gfx.h, this must be fixed
1511 in a future WebGPU update.
1512
1513 - The sokol shader compiler generally adds `diagnostic(off, derivative_uniformity);`
1514 into the WGSL output. Currently only the Chrome WebGPU implementation seems
1515 to recognize this.
1516
1517 - The vertex format SG_VERTEXFORMAT_UINT10_N2 is currently not supported because
1518 WebGPU lacks a matching vertex format (this is currently being worked on though,
1519 as soon as the vertex format shows up in webgpu.h, sokol_gfx.h will add support.
1520
1521 - Likewise, the following sokol-gfx vertex formats are not supported in WebGPU:
1522 R16, R16SN, RG16, RG16SN, RGBA16, RGBA16SN and all PVRTC compressed format.
1523 Unlike unsupported vertex formats, unsupported pixel formats can be queried
1524 in cross-backend code via sg_query_pixel_format() though.
1525
1526 - The Emscripten WebGPU shim currently doesn't support the Closure minification
1527 post-link-step (e.g. currently the emcc argument '--closure 1' or '--closure 2'
1528 will generate broken Javascript code.
1529
1530 - sokol-gfx requires the WebGPU device feature `depth32float-stencil8` to be enabled
1531 (this should be widely supported)
1532
1533 - sokol-gfx expects that the WebGPU device feature `float32-filterable` to *not* be
1534 enabled (since this would exclude all iOS devices)
1535
1536
1537 LICENSE
1538 =======
1539 zlib/libpng license
1540
1541 Copyright (c) 2018 Andre Weissflog
1542
1543 This software is provided 'as-is', without any express or implied warranty.
1544 In no event will the authors be held liable for any damages arising from the
1545 use of this software.
1546
1547 Permission is granted to anyone to use this software for any purpose,
1548 including commercial applications, and to alter it and redistribute it
1549 freely, subject to the following restrictions:
1550
1551 1. The origin of this software must not be misrepresented; you must not
1552 claim that you wrote the original software. If you use this software in a
1553 product, an acknowledgment in the product documentation would be
1554 appreciated but is not required.
1555
1556 2. Altered source versions must be plainly marked as such, and must not
1557 be misrepresented as being the original software.
1558
1559 3. This notice may not be removed or altered from any source
1560 distribution.
1561*/
1562#define SOKOL_GFX_INCLUDED (1)
1563#include <stddef.h> // size_t
1564#include <stdint.h>
1565#include <stdbool.h>
1566
1567#if defined(SOKOL_API_DECL) && !defined(SOKOL_GFX_API_DECL)
1568#define SOKOL_GFX_API_DECL SOKOL_API_DECL
1569#endif
1570#ifndef SOKOL_GFX_API_DECL
1571#if defined(_WIN32) && defined(SOKOL_DLL) && defined(SOKOL_GFX_IMPL)
1572#define SOKOL_GFX_API_DECL __declspec(dllexport)
1573#elif defined(_WIN32) && defined(SOKOL_DLL)
1574#define SOKOL_GFX_API_DECL __declspec(dllimport)
1575#else
1576#define SOKOL_GFX_API_DECL extern
1577#endif
1578#endif
1579
1580#ifdef __cplusplus
1581extern "C" {
1582#endif
1583
1584/*
1585 Resource id typedefs:
1586
1587 sg_buffer: vertex- and index-buffers
1588 sg_image: images used as textures and render targets
1589 sg_sampler sampler object describing how a texture is sampled in a shader
1590 sg_shader: vertex- and fragment-shaders and shader interface information
1591 sg_pipeline: associated shader and vertex-layouts, and render states
1592 sg_attachments: a baked collection of render pass attachment images
1593
1594 Instead of pointers, resource creation functions return a 32-bit
1595 number which uniquely identifies the resource object.
1596
1597 The 32-bit resource id is split into a 16-bit pool index in the lower bits,
1598 and a 16-bit 'generation counter' in the upper bits. The index allows fast
1599 pool lookups, and combined with the generation-counter it allows to detect
1600 'dangling accesses' (trying to use an object which no longer exists, and
1601 its pool slot has been reused for a new object)
1602
1603 The resource ids are wrapped into a strongly-typed struct so that
1604 trying to pass an incompatible resource id is a compile error.
1605*/
1606typedef struct sg_buffer { uint32_t id; } sg_buffer;
1607typedef struct sg_image { uint32_t id; } sg_image;
1608typedef struct sg_sampler { uint32_t id; } sg_sampler;
1609typedef struct sg_shader { uint32_t id; } sg_shader;
1610typedef struct sg_pipeline { uint32_t id; } sg_pipeline;
1611typedef struct sg_attachments { uint32_t id; } sg_attachments;
1612
1613/*
1614 sg_range is a pointer-size-pair struct used to pass memory blobs into
1615 sokol-gfx. When initialized from a value type (array or struct), you can
1616 use the SG_RANGE() macro to build an sg_range struct. For functions which
1617 take either a sg_range pointer, or a (C++) sg_range reference, use the
1618 SG_RANGE_REF macro as a solution which compiles both in C and C++.
1619*/
1620typedef struct sg_range {
1621 const void* ptr;
1622 size_t size;
1623} sg_range;
1624
1625// disabling this for every includer isn't great, but the warnings are also quite pointless
1626#if defined(_MSC_VER)
1627#pragma warning(disable:4221) // /W4 only: nonstandard extension used: 'x': cannot be initialized using address of automatic variable 'y'
1628#pragma warning(disable:4204) // VS2015: nonstandard extension used: non-constant aggregate initializer
1629#endif
1630#if defined(__cplusplus)
1631#define SG_RANGE(x) sg_range{ &x, sizeof(x) }
1632#define SG_RANGE_REF(x) sg_range{ &x, sizeof(x) }
1633#else
1634#define SG_RANGE(x) (sg_range){ &x, sizeof(x) }
1635#define SG_RANGE_REF(x) &(sg_range){ &x, sizeof(x) }
1636#endif
1637
1638// various compile-time constants
1639enum {
1640 SG_INVALID_ID = 0,
1641 SG_NUM_SHADER_STAGES = 2,
1642 SG_NUM_INFLIGHT_FRAMES = 2,
1643 SG_MAX_COLOR_ATTACHMENTS = 4,
1644 SG_MAX_VERTEX_BUFFERS = 8,
1645 SG_MAX_SHADERSTAGE_IMAGES = 12,
1646 SG_MAX_SHADERSTAGE_SAMPLERS = 8,
1647 SG_MAX_SHADERSTAGE_IMAGESAMPLERPAIRS = 12,
1648 SG_MAX_SHADERSTAGE_STORAGEBUFFERS = 8,
1649 SG_MAX_SHADERSTAGE_UBS = 4,
1650 SG_MAX_UB_MEMBERS = 16,
1651 SG_MAX_VERTEX_ATTRIBUTES = 16,
1652 SG_MAX_MIPMAPS = 16,
1653 SG_MAX_TEXTUREARRAY_LAYERS = 128
1654};
1655
1656/*
1657 sg_color
1658
1659 An RGBA color value.
1660*/
1661typedef struct sg_color { float r, g, b, a; } sg_color;
1662
1663/*
1664 sg_backend
1665
1666 The active 3D-API backend, use the function sg_query_backend()
1667 to get the currently active backend.
1668*/
1669typedef enum sg_backend {
1670 SG_BACKEND_GLCORE,
1671 SG_BACKEND_GLES3,
1672 SG_BACKEND_D3D11,
1673 SG_BACKEND_METAL_IOS,
1674 SG_BACKEND_METAL_MACOS,
1675 SG_BACKEND_METAL_SIMULATOR,
1676 SG_BACKEND_WGPU,
1677 SG_BACKEND_DUMMY,
1678} sg_backend;
1679
1680/*
1681 sg_pixel_format
1682
1683 sokol_gfx.h basically uses the same pixel formats as WebGPU, since these
1684 are supported on most newer GPUs.
1685
1686 A pixelformat name consist of three parts:
1687
1688 - components (R, RG, RGB or RGBA)
1689 - bit width per component (8, 16 or 32)
1690 - component data type:
1691 - unsigned normalized (no postfix)
1692 - signed normalized (SN postfix)
1693 - unsigned integer (UI postfix)
1694 - signed integer (SI postfix)
1695 - float (F postfix)
1696
1697 Not all pixel formats can be used for everything, call sg_query_pixelformat()
1698 to inspect the capabilities of a given pixelformat. The function returns
1699 an sg_pixelformat_info struct with the following members:
1700
1701 - sample: the pixelformat can be sampled as texture at least with
1702 nearest filtering
1703 - filter: the pixelformat can be samples as texture with linear
1704 filtering
1705 - render: the pixelformat can be used for render targets
1706 - blend: blending is supported when using the pixelformat for
1707 render targets
1708 - msaa: multisample-antialiasing is supported when using the
1709 pixelformat for render targets
1710 - depth: the pixelformat can be used for depth-stencil attachments
1711 - compressed: this is a block-compressed format
1712 - bytes_per_pixel: the numbers of bytes in a pixel (0 for compressed formats)
1713
1714 The default pixel format for texture images is SG_PIXELFORMAT_RGBA8.
1715
1716 The default pixel format for render target images is platform-dependent
1717 and taken from the sg_environment struct passed into sg_setup(). Typically
1718 the default formats are:
1719
1720 - for the Metal, D3D11 and WebGPU backends: SG_PIXELFORMAT_BGRA8
1721 - for GL backends: SG_PIXELFORMAT_RGBA8
1722*/
1723typedef enum sg_pixel_format {
1724 _SG_PIXELFORMAT_DEFAULT, // value 0 reserved for default-init
1725 SG_PIXELFORMAT_NONE,
1726
1727 SG_PIXELFORMAT_R8,
1728 SG_PIXELFORMAT_R8SN,
1729 SG_PIXELFORMAT_R8UI,
1730 SG_PIXELFORMAT_R8SI,
1731
1732 SG_PIXELFORMAT_R16,
1733 SG_PIXELFORMAT_R16SN,
1734 SG_PIXELFORMAT_R16UI,
1735 SG_PIXELFORMAT_R16SI,
1736 SG_PIXELFORMAT_R16F,
1737 SG_PIXELFORMAT_RG8,
1738 SG_PIXELFORMAT_RG8SN,
1739 SG_PIXELFORMAT_RG8UI,
1740 SG_PIXELFORMAT_RG8SI,
1741
1742 SG_PIXELFORMAT_R32UI,
1743 SG_PIXELFORMAT_R32SI,
1744 SG_PIXELFORMAT_R32F,
1745 SG_PIXELFORMAT_RG16,
1746 SG_PIXELFORMAT_RG16SN,
1747 SG_PIXELFORMAT_RG16UI,
1748 SG_PIXELFORMAT_RG16SI,
1749 SG_PIXELFORMAT_RG16F,
1750 SG_PIXELFORMAT_RGBA8,
1751 SG_PIXELFORMAT_SRGB8A8,
1752 SG_PIXELFORMAT_RGBA8SN,
1753 SG_PIXELFORMAT_RGBA8UI,
1754 SG_PIXELFORMAT_RGBA8SI,
1755 SG_PIXELFORMAT_BGRA8,
1756 SG_PIXELFORMAT_RGB10A2,
1757 SG_PIXELFORMAT_RG11B10F,
1758 SG_PIXELFORMAT_RGB9E5,
1759
1760 SG_PIXELFORMAT_RG32UI,
1761 SG_PIXELFORMAT_RG32SI,
1762 SG_PIXELFORMAT_RG32F,
1763 SG_PIXELFORMAT_RGBA16,
1764 SG_PIXELFORMAT_RGBA16SN,
1765 SG_PIXELFORMAT_RGBA16UI,
1766 SG_PIXELFORMAT_RGBA16SI,
1767 SG_PIXELFORMAT_RGBA16F,
1768
1769 SG_PIXELFORMAT_RGBA32UI,
1770 SG_PIXELFORMAT_RGBA32SI,
1771 SG_PIXELFORMAT_RGBA32F,
1772
1773 // NOTE: when adding/removing pixel formats before DEPTH, also update sokol_app.h/_SAPP_PIXELFORMAT_*
1774 SG_PIXELFORMAT_DEPTH,
1775 SG_PIXELFORMAT_DEPTH_STENCIL,
1776
1777 // NOTE: don't put any new compressed format in front of here
1778 SG_PIXELFORMAT_BC1_RGBA,
1779 SG_PIXELFORMAT_BC2_RGBA,
1780 SG_PIXELFORMAT_BC3_RGBA,
1781 SG_PIXELFORMAT_BC3_SRGBA,
1782 SG_PIXELFORMAT_BC4_R,
1783 SG_PIXELFORMAT_BC4_RSN,
1784 SG_PIXELFORMAT_BC5_RG,
1785 SG_PIXELFORMAT_BC5_RGSN,
1786 SG_PIXELFORMAT_BC6H_RGBF,
1787 SG_PIXELFORMAT_BC6H_RGBUF,
1788 SG_PIXELFORMAT_BC7_RGBA,
1789 SG_PIXELFORMAT_BC7_SRGBA,
1790 SG_PIXELFORMAT_PVRTC_RGB_2BPP, // FIXME: deprecated
1791 SG_PIXELFORMAT_PVRTC_RGB_4BPP, // FIXME: deprecated
1792 SG_PIXELFORMAT_PVRTC_RGBA_2BPP, // FIXME: deprecated
1793 SG_PIXELFORMAT_PVRTC_RGBA_4BPP, // FIXME: deprecated
1794 SG_PIXELFORMAT_ETC2_RGB8,
1795 SG_PIXELFORMAT_ETC2_SRGB8,
1796 SG_PIXELFORMAT_ETC2_RGB8A1,
1797 SG_PIXELFORMAT_ETC2_RGBA8,
1798 SG_PIXELFORMAT_ETC2_SRGB8A8,
1799 SG_PIXELFORMAT_EAC_R11,
1800 SG_PIXELFORMAT_EAC_R11SN,
1801 SG_PIXELFORMAT_EAC_RG11,
1802 SG_PIXELFORMAT_EAC_RG11SN,
1803
1804 SG_PIXELFORMAT_ASTC_4x4_RGBA,
1805 SG_PIXELFORMAT_ASTC_4x4_SRGBA,
1806
1807 _SG_PIXELFORMAT_NUM,
1808 _SG_PIXELFORMAT_FORCE_U32 = 0x7FFFFFFF
1809} sg_pixel_format;
1810
1811/*
1812 Runtime information about a pixel format, returned
1813 by sg_query_pixelformat().
1814*/
1815typedef struct sg_pixelformat_info {
1816 bool sample; // pixel format can be sampled in shaders at least with nearest filtering
1817 bool filter; // pixel format can be sampled with linear filtering
1818 bool render; // pixel format can be used as render target
1819 bool blend; // alpha-blending is supported
1820 bool msaa; // pixel format can be used as MSAA render target
1821 bool depth; // pixel format is a depth format
1822 bool compressed; // true if this is a hardware-compressed format
1823 int bytes_per_pixel; // NOTE: this is 0 for compressed formats, use sg_query_row_pitch() / sg_query_surface_pitch() as alternative
1824} sg_pixelformat_info;
1825
1826/*
1827 Runtime information about available optional features,
1828 returned by sg_query_features()
1829*/
1830typedef struct sg_features {
1831 bool origin_top_left; // framebuffer and texture origin is in top left corner
1832 bool image_clamp_to_border; // border color and clamp-to-border UV-wrap mode is supported
1833 bool mrt_independent_blend_state; // multiple-render-target rendering can use per-render-target blend state
1834 bool mrt_independent_write_mask; // multiple-render-target rendering can use per-render-target color write masks
1835 bool storage_buffer; // storage buffers are supported
1836} sg_features;
1837
1838/*
1839 Runtime information about resource limits, returned by sg_query_limit()
1840*/
1841typedef struct sg_limits {
1842 int max_image_size_2d; // max width/height of SG_IMAGETYPE_2D images
1843 int max_image_size_cube; // max width/height of SG_IMAGETYPE_CUBE images
1844 int max_image_size_3d; // max width/height/depth of SG_IMAGETYPE_3D images
1845 int max_image_size_array; // max width/height of SG_IMAGETYPE_ARRAY images
1846 int max_image_array_layers; // max number of layers in SG_IMAGETYPE_ARRAY images
1847 int max_vertex_attrs; // max number of vertex attributes, clamped to SG_MAX_VERTEX_ATTRIBUTES
1848 int gl_max_vertex_uniform_components; // <= GL_MAX_VERTEX_UNIFORM_COMPONENTS (only on GL backends)
1849 int gl_max_combined_texture_image_units; // <= GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (only on GL backends)
1850} sg_limits;
1851
1852/*
1853 sg_resource_state
1854
1855 The current state of a resource in its resource pool.
1856 Resources start in the INITIAL state, which means the
1857 pool slot is unoccupied and can be allocated. When a resource is
1858 created, first an id is allocated, and the resource pool slot
1859 is set to state ALLOC. After allocation, the resource is
1860 initialized, which may result in the VALID or FAILED state. The
1861 reason why allocation and initialization are separate is because
1862 some resource types (e.g. buffers and images) might be asynchronously
1863 initialized by the user application. If a resource which is not
1864 in the VALID state is attempted to be used for rendering, rendering
1865 operations will silently be dropped.
1866
1867 The special INVALID state is returned in sg_query_xxx_state() if no
1868 resource object exists for the provided resource id.
1869*/
1870typedef enum sg_resource_state {
1871 SG_RESOURCESTATE_INITIAL,
1872 SG_RESOURCESTATE_ALLOC,
1873 SG_RESOURCESTATE_VALID,
1874 SG_RESOURCESTATE_FAILED,
1875 SG_RESOURCESTATE_INVALID,
1876 _SG_RESOURCESTATE_FORCE_U32 = 0x7FFFFFFF
1877} sg_resource_state;
1878
1879/*
1880 sg_usage
1881
1882 A resource usage hint describing the update strategy of
1883 buffers and images. This is used in the sg_buffer_desc.usage
1884 and sg_image_desc.usage members when creating buffers
1885 and images:
1886
1887 SG_USAGE_IMMUTABLE: the resource will never be updated with
1888 new data, instead the content of the
1889 resource must be provided on creation
1890 SG_USAGE_DYNAMIC: the resource will be updated infrequently
1891 with new data (this could range from "once
1892 after creation", to "quite often but not
1893 every frame")
1894 SG_USAGE_STREAM: the resource will be updated each frame
1895 with new content
1896
1897 The rendering backends use this hint to prevent that the
1898 CPU needs to wait for the GPU when attempting to update
1899 a resource that might be currently accessed by the GPU.
1900
1901 Resource content is updated with the functions sg_update_buffer() or
1902 sg_append_buffer() for buffer objects, and sg_update_image() for image
1903 objects. For the sg_update_*() functions, only one update is allowed per
1904 frame and resource object, while sg_append_buffer() can be called
1905 multiple times per frame on the same buffer. The application must update
1906 all data required for rendering (this means that the update data can be
1907 smaller than the resource size, if only a part of the overall resource
1908 size is used for rendering, you only need to make sure that the data that
1909 *is* used is valid).
1910
1911 The default usage is SG_USAGE_IMMUTABLE.
1912*/
1913typedef enum sg_usage {
1914 _SG_USAGE_DEFAULT, // value 0 reserved for default-init
1915 SG_USAGE_IMMUTABLE,
1916 SG_USAGE_DYNAMIC,
1917 SG_USAGE_STREAM,
1918 _SG_USAGE_NUM,
1919 _SG_USAGE_FORCE_U32 = 0x7FFFFFFF
1920} sg_usage;
1921
1922/*
1923 sg_buffer_type
1924
1925 Indicates whether a buffer will be bound as vertex-,
1926 index- or storage-buffer.
1927
1928 Used in the sg_buffer_desc.type member when creating a buffer.
1929
1930 The default value is SG_BUFFERTYPE_VERTEXBUFFER.
1931*/
1932typedef enum sg_buffer_type {
1933 _SG_BUFFERTYPE_DEFAULT, // value 0 reserved for default-init
1934 SG_BUFFERTYPE_VERTEXBUFFER,
1935 SG_BUFFERTYPE_INDEXBUFFER,
1936 SG_BUFFERTYPE_STORAGEBUFFER,
1937 _SG_BUFFERTYPE_NUM,
1938 _SG_BUFFERTYPE_FORCE_U32 = 0x7FFFFFFF
1939} sg_buffer_type;
1940
1941/*
1942 sg_index_type
1943
1944 Indicates whether indexed rendering (fetching vertex-indices from an
1945 index buffer) is used, and if yes, the index data type (16- or 32-bits).
1946 This is used in the sg_pipeline_desc.index_type member when creating a
1947 pipeline object.
1948
1949 The default index type is SG_INDEXTYPE_NONE.
1950*/
1951typedef enum sg_index_type {
1952 _SG_INDEXTYPE_DEFAULT, // value 0 reserved for default-init
1953 SG_INDEXTYPE_NONE,
1954 SG_INDEXTYPE_UINT16,
1955 SG_INDEXTYPE_UINT32,
1956 _SG_INDEXTYPE_NUM,
1957 _SG_INDEXTYPE_FORCE_U32 = 0x7FFFFFFF
1958} sg_index_type;
1959
1960/*
1961 sg_image_type
1962
1963 Indicates the basic type of an image object (2D-texture, cubemap,
1964 3D-texture or 2D-array-texture). Used in the sg_image_desc.type member when
1965 creating an image, and in sg_shader_image_desc to describe a sampled texture
1966 in the shader (both must match and will be checked in the validation layer
1967 when calling sg_apply_bindings).
1968
1969 The default image type when creating an image is SG_IMAGETYPE_2D.
1970*/
1971typedef enum sg_image_type {
1972 _SG_IMAGETYPE_DEFAULT, // value 0 reserved for default-init
1973 SG_IMAGETYPE_2D,
1974 SG_IMAGETYPE_CUBE,
1975 SG_IMAGETYPE_3D,
1976 SG_IMAGETYPE_ARRAY,
1977 _SG_IMAGETYPE_NUM,
1978 _SG_IMAGETYPE_FORCE_U32 = 0x7FFFFFFF
1979} sg_image_type;
1980
1981/*
1982 sg_image_sample_type
1983
1984 The basic data type of a texture sample as expected by a shader.
1985 Must be provided in sg_shader_image_desc and used by the validation
1986 layer in sg_apply_bindings() to check if the provided image object
1987 is compatible with what the shader expects. Apart from the sokol-gfx
1988 validation layer, WebGPU is the only backend API which actually requires
1989 matching texture and sampler type to be provided upfront for validation
1990 (other 3D APIs treat texture/sampler type mismatches as undefined behaviour).
1991
1992 NOTE that the following texture pixel formats require the use
1993 of SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT, combined with a sampler
1994 of type SG_SAMPLERTYPE_NONFILTERING:
1995
1996 - SG_PIXELFORMAT_R32F
1997 - SG_PIXELFORMAT_RG32F
1998 - SG_PIXELFORMAT_RGBA32F
1999
2000 (when using sokol-shdc, also check out the meta tags `@image_sample_type`
2001 and `@sampler_type`)
2002*/
2003typedef enum sg_image_sample_type {
2004 _SG_IMAGESAMPLETYPE_DEFAULT, // value 0 reserved for default-init
2005 SG_IMAGESAMPLETYPE_FLOAT,
2006 SG_IMAGESAMPLETYPE_DEPTH,
2007 SG_IMAGESAMPLETYPE_SINT,
2008 SG_IMAGESAMPLETYPE_UINT,
2009 SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT,
2010 _SG_IMAGESAMPLETYPE_NUM,
2011 _SG_IMAGESAMPLETYPE_FORCE_U32 = 0x7FFFFFFF
2012} sg_image_sample_type;
2013
2014/*
2015 sg_sampler_type
2016
2017 The basic type of a texture sampler (sampling vs comparison) as
2018 defined in a shader. Must be provided in sg_shader_sampler_desc.
2019
2020 sg_image_sample_type and sg_sampler_type for a texture/sampler
2021 pair must be compatible with each other, specifically only
2022 the following pairs are allowed:
2023
2024 - SG_IMAGESAMPLETYPE_FLOAT => (SG_SAMPLERTYPE_FILTERING or SG_SAMPLERTYPE_NONFILTERING)
2025 - SG_IMAGESAMPLETYPE_UNFILTERABLE_FLOAT => SG_SAMPLERTYPE_NONFILTERING
2026 - SG_IMAGESAMPLETYPE_SINT => SG_SAMPLERTYPE_NONFILTERING
2027 - SG_IMAGESAMPLETYPE_UINT => SG_SAMPLERTYPE_NONFILTERING
2028 - SG_IMAGESAMPLETYPE_DEPTH => SG_SAMPLERTYPE_COMPARISON
2029*/
2030typedef enum sg_sampler_type {
2031 _SG_SAMPLERTYPE_DEFAULT,
2032 SG_SAMPLERTYPE_FILTERING,
2033 SG_SAMPLERTYPE_NONFILTERING,
2034 SG_SAMPLERTYPE_COMPARISON,
2035 _SG_SAMPLERTYPE_NUM,
2036 _SG_SAMPLERTYPE_FORCE_U32,
2037} sg_sampler_type;
2038
2039/*
2040 sg_cube_face
2041
2042 The cubemap faces. Use these as indices in the sg_image_desc.content
2043 array.
2044*/
2045typedef enum sg_cube_face {
2046 SG_CUBEFACE_POS_X,
2047 SG_CUBEFACE_NEG_X,
2048 SG_CUBEFACE_POS_Y,
2049 SG_CUBEFACE_NEG_Y,
2050 SG_CUBEFACE_POS_Z,
2051 SG_CUBEFACE_NEG_Z,
2052 SG_CUBEFACE_NUM,
2053 _SG_CUBEFACE_FORCE_U32 = 0x7FFFFFFF
2054} sg_cube_face;
2055
2056/*
2057 sg_shader_stage
2058
2059 There are 2 shader stages: vertex- and fragment-shader-stage.
2060 Each shader stage
2061
2062 - SG_MAX_SHADERSTAGE_UBS slots for applying uniform data
2063 - SG_MAX_SHADERSTAGE_IMAGES slots for images used as textures
2064 - SG_MAX_SHADERSTAGE_SAMPLERS slots for texture samplers
2065 - SG_MAX_SHADERSTAGE_STORAGEBUFFERS slots for storage buffer bindings
2066*/
2067typedef enum sg_shader_stage {
2068 SG_SHADERSTAGE_VS,
2069 SG_SHADERSTAGE_FS,
2070 _SG_SHADERSTAGE_FORCE_U32 = 0x7FFFFFFF
2071} sg_shader_stage;
2072
2073/*
2074 sg_primitive_type
2075
2076 This is the common subset of 3D primitive types supported across all 3D
2077 APIs. This is used in the sg_pipeline_desc.primitive_type member when
2078 creating a pipeline object.
2079
2080 The default primitive type is SG_PRIMITIVETYPE_TRIANGLES.
2081*/
2082typedef enum sg_primitive_type {
2083 _SG_PRIMITIVETYPE_DEFAULT, // value 0 reserved for default-init
2084 SG_PRIMITIVETYPE_POINTS,
2085 SG_PRIMITIVETYPE_LINES,
2086 SG_PRIMITIVETYPE_LINE_STRIP,
2087 SG_PRIMITIVETYPE_TRIANGLES,
2088 SG_PRIMITIVETYPE_TRIANGLE_STRIP,
2089 _SG_PRIMITIVETYPE_NUM,
2090 _SG_PRIMITIVETYPE_FORCE_U32 = 0x7FFFFFFF
2091} sg_primitive_type;
2092
2093/*
2094 sg_filter
2095
2096 The filtering mode when sampling a texture image. This is
2097 used in the sg_sampler_desc.min_filter, sg_sampler_desc.mag_filter
2098 and sg_sampler_desc.mipmap_filter members when creating a sampler object.
2099
2100 For min_filter and mag_filter the default is SG_FILTER_NEAREST.
2101
2102 For mipmap_filter the default is SG_FILTER_NONE.
2103*/
2104typedef enum sg_filter {
2105 _SG_FILTER_DEFAULT, // value 0 reserved for default-init
2106 SG_FILTER_NONE, // FIXME: deprecated
2107 SG_FILTER_NEAREST,
2108 SG_FILTER_LINEAR,
2109 _SG_FILTER_NUM,
2110 _SG_FILTER_FORCE_U32 = 0x7FFFFFFF
2111} sg_filter;
2112
2113/*
2114 sg_wrap
2115
2116 The texture coordinates wrapping mode when sampling a texture
2117 image. This is used in the sg_image_desc.wrap_u, .wrap_v
2118 and .wrap_w members when creating an image.
2119
2120 The default wrap mode is SG_WRAP_REPEAT.
2121
2122 NOTE: SG_WRAP_CLAMP_TO_BORDER is not supported on all backends
2123 and platforms. To check for support, call sg_query_features()
2124 and check the "clamp_to_border" boolean in the returned
2125 sg_features struct.
2126
2127 Platforms which don't support SG_WRAP_CLAMP_TO_BORDER will silently fall back
2128 to SG_WRAP_CLAMP_TO_EDGE without a validation error.
2129*/
2130typedef enum sg_wrap {
2131 _SG_WRAP_DEFAULT, // value 0 reserved for default-init
2132 SG_WRAP_REPEAT,
2133 SG_WRAP_CLAMP_TO_EDGE,
2134 SG_WRAP_CLAMP_TO_BORDER,
2135 SG_WRAP_MIRRORED_REPEAT,
2136 _SG_WRAP_NUM,
2137 _SG_WRAP_FORCE_U32 = 0x7FFFFFFF
2138} sg_wrap;
2139
2140/*
2141 sg_border_color
2142
2143 The border color to use when sampling a texture, and the UV wrap
2144 mode is SG_WRAP_CLAMP_TO_BORDER.
2145
2146 The default border color is SG_BORDERCOLOR_OPAQUE_BLACK
2147*/
2148typedef enum sg_border_color {
2149 _SG_BORDERCOLOR_DEFAULT, // value 0 reserved for default-init
2150 SG_BORDERCOLOR_TRANSPARENT_BLACK,
2151 SG_BORDERCOLOR_OPAQUE_BLACK,
2152 SG_BORDERCOLOR_OPAQUE_WHITE,
2153 _SG_BORDERCOLOR_NUM,
2154 _SG_BORDERCOLOR_FORCE_U32 = 0x7FFFFFFF
2155} sg_border_color;
2156
2157/*
2158 sg_vertex_format
2159
2160 The data type of a vertex component. This is used to describe
2161 the layout of vertex data when creating a pipeline object.
2162*/
2163typedef enum sg_vertex_format {
2164 SG_VERTEXFORMAT_INVALID,
2165 SG_VERTEXFORMAT_FLOAT,
2166 SG_VERTEXFORMAT_FLOAT2,
2167 SG_VERTEXFORMAT_FLOAT3,
2168 SG_VERTEXFORMAT_FLOAT4,
2169 SG_VERTEXFORMAT_BYTE4,
2170 SG_VERTEXFORMAT_BYTE4N,
2171 SG_VERTEXFORMAT_UBYTE4,
2172 SG_VERTEXFORMAT_UBYTE4N,
2173 SG_VERTEXFORMAT_SHORT2,
2174 SG_VERTEXFORMAT_SHORT2N,
2175 SG_VERTEXFORMAT_USHORT2N,
2176 SG_VERTEXFORMAT_SHORT4,
2177 SG_VERTEXFORMAT_SHORT4N,
2178 SG_VERTEXFORMAT_USHORT4N,
2179 SG_VERTEXFORMAT_UINT10_N2,
2180 SG_VERTEXFORMAT_HALF2,
2181 SG_VERTEXFORMAT_HALF4,
2182 _SG_VERTEXFORMAT_NUM,
2183 _SG_VERTEXFORMAT_FORCE_U32 = 0x7FFFFFFF
2184} sg_vertex_format;
2185
2186/*
2187 sg_vertex_step
2188
2189 Defines whether the input pointer of a vertex input stream is advanced
2190 'per vertex' or 'per instance'. The default step-func is
2191 SG_VERTEXSTEP_PER_VERTEX. SG_VERTEXSTEP_PER_INSTANCE is used with
2192 instanced-rendering.
2193
2194 The vertex-step is part of the vertex-layout definition
2195 when creating pipeline objects.
2196*/
2197typedef enum sg_vertex_step {
2198 _SG_VERTEXSTEP_DEFAULT, // value 0 reserved for default-init
2199 SG_VERTEXSTEP_PER_VERTEX,
2200 SG_VERTEXSTEP_PER_INSTANCE,
2201 _SG_VERTEXSTEP_NUM,
2202 _SG_VERTEXSTEP_FORCE_U32 = 0x7FFFFFFF
2203} sg_vertex_step;
2204
2205/*
2206 sg_uniform_type
2207
2208 The data type of a uniform block member. This is used to
2209 describe the internal layout of uniform blocks when creating
2210 a shader object.
2211*/
2212typedef enum sg_uniform_type {
2213 SG_UNIFORMTYPE_INVALID,
2214 SG_UNIFORMTYPE_FLOAT,
2215 SG_UNIFORMTYPE_FLOAT2,
2216 SG_UNIFORMTYPE_FLOAT3,
2217 SG_UNIFORMTYPE_FLOAT4,
2218 SG_UNIFORMTYPE_INT,
2219 SG_UNIFORMTYPE_INT2,
2220 SG_UNIFORMTYPE_INT3,
2221 SG_UNIFORMTYPE_INT4,
2222 SG_UNIFORMTYPE_MAT4,
2223 _SG_UNIFORMTYPE_NUM,
2224 _SG_UNIFORMTYPE_FORCE_U32 = 0x7FFFFFFF
2225} sg_uniform_type;
2226
2227/*
2228 sg_uniform_layout
2229
2230 A hint for the interior memory layout of uniform blocks. This is
2231 only really relevant for the GL backend where the internal layout
2232 of uniform blocks must be known to sokol-gfx. For all other backends the
2233 internal memory layout of uniform blocks doesn't matter, sokol-gfx
2234 will just pass uniform data as a single memory blob to the
2235 3D backend.
2236
2237 SG_UNIFORMLAYOUT_NATIVE (default)
2238 Native layout means that a 'backend-native' memory layout
2239 is used. For the GL backend this means that uniforms
2240 are packed tightly in memory (e.g. there are no padding
2241 bytes).
2242
2243 SG_UNIFORMLAYOUT_STD140
2244 The memory layout is a subset of std140. Arrays are only
2245 allowed for the FLOAT4, INT4 and MAT4. Alignment is as
2246 is as follows:
2247
2248 FLOAT, INT: 4 byte alignment
2249 FLOAT2, INT2: 8 byte alignment
2250 FLOAT3, INT3: 16 byte alignment(!)
2251 FLOAT4, INT4: 16 byte alignment
2252 MAT4: 16 byte alignment
2253 FLOAT4[], INT4[]: 16 byte alignment
2254
2255 The overall size of the uniform block must be a multiple
2256 of 16.
2257
2258 For more information search for 'UNIFORM DATA LAYOUT' in the documentation block
2259 at the start of the header.
2260*/
2261typedef enum sg_uniform_layout {
2262 _SG_UNIFORMLAYOUT_DEFAULT, // value 0 reserved for default-init
2263 SG_UNIFORMLAYOUT_NATIVE, // default: layout depends on currently active backend
2264 SG_UNIFORMLAYOUT_STD140, // std140: memory layout according to std140
2265 _SG_UNIFORMLAYOUT_NUM,
2266 _SG_UNIFORMLAYOUT_FORCE_U32 = 0x7FFFFFFF
2267} sg_uniform_layout;
2268
2269/*
2270 sg_cull_mode
2271
2272 The face-culling mode, this is used in the
2273 sg_pipeline_desc.cull_mode member when creating a
2274 pipeline object.
2275
2276 The default cull mode is SG_CULLMODE_NONE
2277*/
2278typedef enum sg_cull_mode {
2279 _SG_CULLMODE_DEFAULT, // value 0 reserved for default-init
2280 SG_CULLMODE_NONE,
2281 SG_CULLMODE_FRONT,
2282 SG_CULLMODE_BACK,
2283 _SG_CULLMODE_NUM,
2284 _SG_CULLMODE_FORCE_U32 = 0x7FFFFFFF
2285} sg_cull_mode;
2286
2287/*
2288 sg_face_winding
2289
2290 The vertex-winding rule that determines a front-facing primitive. This
2291 is used in the member sg_pipeline_desc.face_winding
2292 when creating a pipeline object.
2293
2294 The default winding is SG_FACEWINDING_CW (clockwise)
2295*/
2296typedef enum sg_face_winding {
2297 _SG_FACEWINDING_DEFAULT, // value 0 reserved for default-init
2298 SG_FACEWINDING_CCW,
2299 SG_FACEWINDING_CW,
2300 _SG_FACEWINDING_NUM,
2301 _SG_FACEWINDING_FORCE_U32 = 0x7FFFFFFF
2302} sg_face_winding;
2303
2304/*
2305 sg_compare_func
2306
2307 The compare-function for configuring depth- and stencil-ref tests
2308 in pipeline objects, and for texture samplers which perform a comparison
2309 instead of regular sampling operation.
2310
2311 sg_pipeline_desc
2312 .depth
2313 .compare
2314 .stencil
2315 .front.compare
2316 .back.compar
2317
2318 sg_sampler_desc
2319 .compare
2320
2321 The default compare func for depth- and stencil-tests is
2322 SG_COMPAREFUNC_ALWAYS.
2323
2324 The default compare func for sampler is SG_COMPAREFUNC_NEVER.
2325*/
2326typedef enum sg_compare_func {
2327 _SG_COMPAREFUNC_DEFAULT, // value 0 reserved for default-init
2328 SG_COMPAREFUNC_NEVER,
2329 SG_COMPAREFUNC_LESS,
2330 SG_COMPAREFUNC_EQUAL,
2331 SG_COMPAREFUNC_LESS_EQUAL,
2332 SG_COMPAREFUNC_GREATER,
2333 SG_COMPAREFUNC_NOT_EQUAL,
2334 SG_COMPAREFUNC_GREATER_EQUAL,
2335 SG_COMPAREFUNC_ALWAYS,
2336 _SG_COMPAREFUNC_NUM,
2337 _SG_COMPAREFUNC_FORCE_U32 = 0x7FFFFFFF
2338} sg_compare_func;
2339
2340/*
2341 sg_stencil_op
2342
2343 The operation performed on a currently stored stencil-value when a
2344 comparison test passes or fails. This is used when creating a pipeline
2345 object in the members:
2346
2347 sg_pipeline_desc
2348 .stencil
2349 .front
2350 .fail_op
2351 .depth_fail_op
2352 .pass_op
2353 .back
2354 .fail_op
2355 .depth_fail_op
2356 .pass_op
2357
2358 The default value is SG_STENCILOP_KEEP.
2359*/
2360typedef enum sg_stencil_op {
2361 _SG_STENCILOP_DEFAULT, // value 0 reserved for default-init
2362 SG_STENCILOP_KEEP,
2363 SG_STENCILOP_ZERO,
2364 SG_STENCILOP_REPLACE,
2365 SG_STENCILOP_INCR_CLAMP,
2366 SG_STENCILOP_DECR_CLAMP,
2367 SG_STENCILOP_INVERT,
2368 SG_STENCILOP_INCR_WRAP,
2369 SG_STENCILOP_DECR_WRAP,
2370 _SG_STENCILOP_NUM,
2371 _SG_STENCILOP_FORCE_U32 = 0x7FFFFFFF
2372} sg_stencil_op;
2373
2374/*
2375 sg_blend_factor
2376
2377 The source and destination factors in blending operations.
2378 This is used in the following members when creating a pipeline object:
2379
2380 sg_pipeline_desc
2381 .colors[i]
2382 .blend
2383 .src_factor_rgb
2384 .dst_factor_rgb
2385 .src_factor_alpha
2386 .dst_factor_alpha
2387
2388 The default value is SG_BLENDFACTOR_ONE for source
2389 factors, and SG_BLENDFACTOR_ZERO for destination factors.
2390*/
2391typedef enum sg_blend_factor {
2392 _SG_BLENDFACTOR_DEFAULT, // value 0 reserved for default-init
2393 SG_BLENDFACTOR_ZERO,
2394 SG_BLENDFACTOR_ONE,
2395 SG_BLENDFACTOR_SRC_COLOR,
2396 SG_BLENDFACTOR_ONE_MINUS_SRC_COLOR,
2397 SG_BLENDFACTOR_SRC_ALPHA,
2398 SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
2399 SG_BLENDFACTOR_DST_COLOR,
2400 SG_BLENDFACTOR_ONE_MINUS_DST_COLOR,
2401 SG_BLENDFACTOR_DST_ALPHA,
2402 SG_BLENDFACTOR_ONE_MINUS_DST_ALPHA,
2403 SG_BLENDFACTOR_SRC_ALPHA_SATURATED,
2404 SG_BLENDFACTOR_BLEND_COLOR,
2405 SG_BLENDFACTOR_ONE_MINUS_BLEND_COLOR,
2406 SG_BLENDFACTOR_BLEND_ALPHA,
2407 SG_BLENDFACTOR_ONE_MINUS_BLEND_ALPHA,
2408 _SG_BLENDFACTOR_NUM,
2409 _SG_BLENDFACTOR_FORCE_U32 = 0x7FFFFFFF
2410} sg_blend_factor;
2411
2412/*
2413 sg_blend_op
2414
2415 Describes how the source and destination values are combined in the
2416 fragment blending operation. It is used in the following members when
2417 creating a pipeline object:
2418
2419 sg_pipeline_desc
2420 .colors[i]
2421 .blend
2422 .op_rgb
2423 .op_alpha
2424
2425 The default value is SG_BLENDOP_ADD.
2426*/
2427typedef enum sg_blend_op {
2428 _SG_BLENDOP_DEFAULT, // value 0 reserved for default-init
2429 SG_BLENDOP_ADD,
2430 SG_BLENDOP_SUBTRACT,
2431 SG_BLENDOP_REVERSE_SUBTRACT,
2432 _SG_BLENDOP_NUM,
2433 _SG_BLENDOP_FORCE_U32 = 0x7FFFFFFF
2434} sg_blend_op;
2435
2436/*
2437 sg_color_mask
2438
2439 Selects the active color channels when writing a fragment color to the
2440 framebuffer. This is used in the members
2441 sg_pipeline_desc.colors[i].write_mask when creating a pipeline object.
2442
2443 The default colormask is SG_COLORMASK_RGBA (write all colors channels)
2444
2445 NOTE: since the color mask value 0 is reserved for the default value
2446 (SG_COLORMASK_RGBA), use SG_COLORMASK_NONE if all color channels
2447 should be disabled.
2448*/
2449typedef enum sg_color_mask {
2450 _SG_COLORMASK_DEFAULT = 0, // value 0 reserved for default-init
2451 SG_COLORMASK_NONE = 0x10, // special value for 'all channels disabled
2452 SG_COLORMASK_R = 0x1,
2453 SG_COLORMASK_G = 0x2,
2454 SG_COLORMASK_RG = 0x3,
2455 SG_COLORMASK_B = 0x4,
2456 SG_COLORMASK_RB = 0x5,
2457 SG_COLORMASK_GB = 0x6,
2458 SG_COLORMASK_RGB = 0x7,
2459 SG_COLORMASK_A = 0x8,
2460 SG_COLORMASK_RA = 0x9,
2461 SG_COLORMASK_GA = 0xA,
2462 SG_COLORMASK_RGA = 0xB,
2463 SG_COLORMASK_BA = 0xC,
2464 SG_COLORMASK_RBA = 0xD,
2465 SG_COLORMASK_GBA = 0xE,
2466 SG_COLORMASK_RGBA = 0xF,
2467 _SG_COLORMASK_FORCE_U32 = 0x7FFFFFFF
2468} sg_color_mask;
2469
2470/*
2471 sg_load_action
2472
2473 Defines the load action that should be performed at the start of a render pass:
2474
2475 SG_LOADACTION_CLEAR: clear the render target
2476 SG_LOADACTION_LOAD: load the previous content of the render target
2477 SG_LOADACTION_DONTCARE: leave the render target in an undefined state
2478
2479 This is used in the sg_pass_action structure.
2480
2481 The default load action for all pass attachments is SG_LOADACTION_CLEAR,
2482 with the values rgba = { 0.5f, 0.5f, 0.5f, 1.0f }, depth=1.0f and stencil=0.
2483
2484 If you want to override the default behaviour, it is important to not
2485 only set the clear color, but the 'action' field as well (as long as this
2486 is _SG_LOADACTION_DEFAULT, the value fields will be ignored).
2487*/
2488typedef enum sg_load_action {
2489 _SG_LOADACTION_DEFAULT,
2490 SG_LOADACTION_CLEAR,
2491 SG_LOADACTION_LOAD,
2492 SG_LOADACTION_DONTCARE,
2493 _SG_LOADACTION_FORCE_U32 = 0x7FFFFFFF
2494} sg_load_action;
2495
2496/*
2497 sg_store_action
2498
2499 Defines the store action that be performed at the end of a render pass:
2500
2501 SG_STOREACTION_STORE: store the rendered content to the color attachment image
2502 SG_STOREACTION_DONTCARE: allows the GPU to discard the rendered content
2503*/
2504typedef enum sg_store_action {
2505 _SG_STOREACTION_DEFAULT,
2506 SG_STOREACTION_STORE,
2507 SG_STOREACTION_DONTCARE,
2508 _SG_STOREACTION_FORCE_U32 = 0x7FFFFFFF
2509} sg_store_action;
2510
2511
2512/*
2513 sg_pass_action
2514
2515 The sg_pass_action struct defines the actions to be performed
2516 at the start and end of a render pass.
2517
2518 - at the start of the pass: whether the render targets should be cleared,
2519 loaded with their previous content, or start in an undefined state
2520 - for clear operations: the clear value (color, depth, or stencil values)
2521 - at the end of the pass: whether the rendering result should be
2522 stored back into the render target or discarded
2523*/
2524typedef struct sg_color_attachment_action {
2525 sg_load_action load_action; // default: SG_LOADACTION_CLEAR
2526 sg_store_action store_action; // default: SG_STOREACTION_STORE
2527 sg_color clear_value; // default: { 0.5f, 0.5f, 0.5f, 1.0f }
2528} sg_color_attachment_action;
2529
2530typedef struct sg_depth_attachment_action {
2531 sg_load_action load_action; // default: SG_LOADACTION_CLEAR
2532 sg_store_action store_action; // default: SG_STOREACTION_DONTCARE
2533 float clear_value; // default: 1.0
2534} sg_depth_attachment_action;
2535
2536typedef struct sg_stencil_attachment_action {
2537 sg_load_action load_action; // default: SG_LOADACTION_CLEAR
2538 sg_store_action store_action; // default: SG_STOREACTION_DONTCARE
2539 uint8_t clear_value; // default: 0
2540} sg_stencil_attachment_action;
2541
2542typedef struct sg_pass_action {
2543 sg_color_attachment_action colors[SG_MAX_COLOR_ATTACHMENTS];
2544 sg_depth_attachment_action depth;
2545 sg_stencil_attachment_action stencil;
2546} sg_pass_action;
2547
2548/*
2549 sg_swapchain
2550
2551 Used in sg_begin_pass() to provide details about an external swapchain
2552 (pixel formats, sample count and backend-API specific render surface objects).
2553
2554 The following information must be provided:
2555
2556 - the width and height of the swapchain surfaces in number of pixels,
2557 - the pixel format of the render- and optional msaa-resolve-surface
2558 - the pixel format of the optional depth- or depth-stencil-surface
2559 - the MSAA sample count for the render and depth-stencil surface
2560
2561 If the pixel formats and MSAA sample counts are left zero-initialized,
2562 their defaults are taken from the sg_environment struct provided in the
2563 sg_setup() call.
2564
2565 The width and height *must* be > 0.
2566
2567 Additionally the following backend API specific objects must be passed in
2568 as 'type erased' void pointers:
2569
2570 GL: on all GL backends, a GL framebuffer object must be provided. This
2571 can be zero for the default framebuffer.
2572
2573 D3D11:
2574 - an ID3D11RenderTargetView for the rendering surface, without
2575 MSAA rendering this surface will also be displayed
2576 - an optional ID3D11DepthStencilView for the depth- or depth/stencil
2577 buffer surface
2578 - when MSAA rendering is used, another ID3D11RenderTargetView
2579 which serves as MSAA resolve target and will be displayed
2580
2581 WebGPU (same as D3D11, except different types)
2582 - a WGPUTextureView for the rendering surface, without
2583 MSAA rendering this surface will also be displayed
2584 - an optional WGPUTextureView for the depth- or depth/stencil
2585 buffer surface
2586 - when MSAA rendering is used, another WGPUTextureView
2587 which serves as MSAA resolve target and will be displayed
2588
2589 Metal (NOTE that the rolves of provided surfaces is slightly different
2590 than on D3D11 or WebGPU in case of MSAA vs non-MSAA rendering):
2591
2592 - A current CAMetalDrawable (NOT an MTLDrawable!) which will be presented.
2593 This will either be rendered to directly (if no MSAA is used), or serve
2594 as MSAA-resolve target.
2595 - an optional MTLTexture for the depth- or depth-stencil buffer
2596 - an optional multisampled MTLTexture which serves as intermediate
2597 rendering surface which will then be resolved into the
2598 CAMetalDrawable.
2599
2600 NOTE that for Metal you must use an ObjC __bridge cast to
2601 properly tunnel the ObjC object handle through a C void*, e.g.:
2602
2603 swapchain.metal.current_drawable = (__bridge const void*) [mtkView currentDrawable];
2604
2605 On all other backends you shouldn't need to mess with the reference count.
2606
2607 It's a good practice to write a helper function which returns an initialized
2608 sg_swapchain structs, which can then be plugged directly into
2609 sg_pass.swapchain. Look at the function sglue_swapchain() in the sokol_glue.h
2610 as an example.
2611*/
2612typedef struct sg_metal_swapchain {
2613 const void* current_drawable; // CAMetalDrawable (NOT MTLDrawable!!!)
2614 const void* depth_stencil_texture; // MTLTexture
2615 const void* msaa_color_texture; // MTLTexture
2616} sg_metal_swapchain;
2617
2618typedef struct sg_d3d11_swapchain {
2619 const void* render_view; // ID3D11RenderTargetView
2620 const void* resolve_view; // ID3D11RenderTargetView
2621 const void* depth_stencil_view; // ID3D11DepthStencilView
2622} sg_d3d11_swapchain;
2623
2624typedef struct sg_wgpu_swapchain {
2625 const void* render_view; // WGPUTextureView
2626 const void* resolve_view; // WGPUTextureView
2627 const void* depth_stencil_view; // WGPUTextureView
2628} sg_wgpu_swapchain;
2629
2630typedef struct sg_gl_swapchain {
2631 uint32_t framebuffer; // GL framebuffer object
2632} sg_gl_swapchain;
2633
2634typedef struct sg_swapchain {
2635 int width;
2636 int height;
2637 int sample_count;
2638 sg_pixel_format color_format;
2639 sg_pixel_format depth_format;
2640 sg_metal_swapchain metal;
2641 sg_d3d11_swapchain d3d11;
2642 sg_wgpu_swapchain wgpu;
2643 sg_gl_swapchain gl;
2644} sg_swapchain;
2645
2646/*
2647 sg_pass
2648
2649 The sg_pass structure is passed as argument into the sg_begin_pass()
2650 function.
2651
2652 For an offscreen rendering pass, an sg_pass_action struct and sg_attachments
2653 object must be provided, and for swapchain passes, and sg_pass_action and
2654 an sg_swapchain struct. It is an error to provide both an sg_attachments
2655 handle and an initialized sg_swapchain struct in the same sg_begin_pass().
2656
2657 An sg_begin_pass() call for an offscreen pass would look like this (where
2658 `attachments` is an sg_attachments handle):
2659
2660 sg_begin_pass(&(sg_pass){
2661 .action = { ... },
2662 .attachments = attachments,
2663 });
2664
2665 ...and a swapchain render pass would look like this (using the sokol_glue.h
2666 helper function sglue_swapchain() which gets the swapchain properties from
2667 sokol_app.h):
2668
2669 sg_begin_pass(&(sg_pass){
2670 .action = { ... },
2671 .swapchain = sglue_swapchain(),
2672 });
2673
2674 You can also omit the .action object to get default pass action behaviour
2675 (clear to color=grey, depth=1 and stencil=0).
2676*/
2677typedef struct sg_pass {
2678 uint32_t _start_canary;
2679 sg_pass_action action;
2680 sg_attachments attachments;
2681 sg_swapchain swapchain;
2682 const char* label;
2683 uint32_t _end_canary;
2684} sg_pass;
2685
2686/*
2687 sg_bindings
2688
2689 The sg_bindings structure defines the resource binding slots
2690 of the sokol_gfx render pipeline, used as argument to the
2691 sg_apply_bindings() function.
2692
2693 A resource binding struct contains:
2694
2695 - 1..N vertex buffers
2696 - 0..N vertex buffer offsets
2697 - 0..1 index buffers
2698 - 0..1 index buffer offsets
2699 - 0..N vertex shader stage images
2700 - 0..N vertex shader stage samplers
2701 - 0..N vertex shader storage buffers
2702 - 0..N fragment shader stage images
2703 - 0..N fragment shader stage samplers
2704 - 0..N fragment shader storage buffers
2705
2706 For the max number of bindings, see the constant definitions:
2707
2708 - SG_MAX_VERTEX_BUFFERS
2709 - SG_MAX_SHADERSTAGE_IMAGES
2710 - SG_MAX_SHADERSTAGE_SAMPLERS
2711 - SG_MAX_SHADERSTAGE_STORAGEBUFFERS
2712
2713 The optional buffer offsets can be used to put different unrelated
2714 chunks of vertex- and/or index-data into the same buffer objects.
2715*/
2716typedef struct sg_stage_bindings {
2717 sg_image images[SG_MAX_SHADERSTAGE_IMAGES];
2718 sg_sampler samplers[SG_MAX_SHADERSTAGE_SAMPLERS];
2719 sg_buffer storage_buffers[SG_MAX_SHADERSTAGE_STORAGEBUFFERS];
2720} sg_stage_bindings;
2721
2722typedef struct sg_bindings {
2723 uint32_t _start_canary;
2724 sg_buffer vertex_buffers[SG_MAX_VERTEX_BUFFERS];
2725 int vertex_buffer_offsets[SG_MAX_VERTEX_BUFFERS];
2726 sg_buffer index_buffer;
2727 int index_buffer_offset;
2728 sg_stage_bindings vs;
2729 sg_stage_bindings fs;
2730 uint32_t _end_canary;
2731} sg_bindings;
2732
2733/*
2734 sg_buffer_desc
2735
2736 Creation parameters for sg_buffer objects, used in the
2737 sg_make_buffer() call.
2738
2739 The default configuration is:
2740
2741 .size: 0 (*must* be >0 for buffers without data)
2742 .type: SG_BUFFERTYPE_VERTEXBUFFER
2743 .usage: SG_USAGE_IMMUTABLE
2744 .data.ptr 0 (*must* be valid for immutable buffers)
2745 .data.size 0 (*must* be > 0 for immutable buffers)
2746 .label 0 (optional string label)
2747
2748 For immutable buffers which are initialized with initial data,
2749 keep the .size item zero-initialized, and set the size together with the
2750 pointer to the initial data in the .data item.
2751
2752 For mutable buffers without initial data, keep the .data item
2753 zero-initialized, and set the buffer size in the .size item instead.
2754
2755 You can also set both size values, but currently both size values must
2756 be identical (this may change in the future when the dynamic resource
2757 management may become more flexible).
2758
2759 ADVANCED TOPIC: Injecting native 3D-API buffers:
2760
2761 The following struct members allow to inject your own GL, Metal
2762 or D3D11 buffers into sokol_gfx:
2763
2764 .gl_buffers[SG_NUM_INFLIGHT_FRAMES]
2765 .mtl_buffers[SG_NUM_INFLIGHT_FRAMES]
2766 .d3d11_buffer
2767
2768 You must still provide all other struct items except the .data item, and
2769 these must match the creation parameters of the native buffers you
2770 provide. For SG_USAGE_IMMUTABLE, only provide a single native 3D-API
2771 buffer, otherwise you need to provide SG_NUM_INFLIGHT_FRAMES buffers
2772 (only for GL and Metal, not D3D11). Providing multiple buffers for GL and
2773 Metal is necessary because sokol_gfx will rotate through them when
2774 calling sg_update_buffer() to prevent lock-stalls.
2775
2776 Note that it is expected that immutable injected buffer have already been
2777 initialized with content, and the .content member must be 0!
2778
2779 Also you need to call sg_reset_state_cache() after calling native 3D-API
2780 functions, and before calling any sokol_gfx function.
2781*/
2782typedef struct sg_buffer_desc {
2783 uint32_t _start_canary;
2784 size_t size;
2785 sg_buffer_type type;
2786 sg_usage usage;
2787 sg_range data;
2788 const char* label;
2789 // optionally inject backend-specific resources
2790 uint32_t gl_buffers[SG_NUM_INFLIGHT_FRAMES];
2791 const void* mtl_buffers[SG_NUM_INFLIGHT_FRAMES];
2792 const void* d3d11_buffer;
2793 const void* wgpu_buffer;
2794 uint32_t _end_canary;
2795} sg_buffer_desc;
2796
2797/*
2798 sg_image_data
2799
2800 Defines the content of an image through a 2D array of sg_range structs.
2801 The first array dimension is the cubemap face, and the second array
2802 dimension the mipmap level.
2803*/
2804typedef struct sg_image_data {
2805 sg_range subimage[SG_CUBEFACE_NUM][SG_MAX_MIPMAPS];
2806} sg_image_data;
2807
2808/*
2809 sg_image_desc
2810
2811 Creation parameters for sg_image objects, used in the sg_make_image() call.
2812
2813 The default configuration is:
2814
2815 .type: SG_IMAGETYPE_2D
2816 .render_target: false
2817 .width 0 (must be set to >0)
2818 .height 0 (must be set to >0)
2819 .num_slices 1 (3D textures: depth; array textures: number of layers)
2820 .num_mipmaps: 1
2821 .usage: SG_USAGE_IMMUTABLE
2822 .pixel_format: SG_PIXELFORMAT_RGBA8 for textures, or sg_desc.environment.defaults.color_format for render targets
2823 .sample_count: 1 for textures, or sg_desc.environment.defaults.sample_count for render targets
2824 .data an sg_image_data struct to define the initial content
2825 .label 0 (optional string label for trace hooks)
2826
2827 Q: Why is the default sample_count for render targets identical with the
2828 "default sample count" from sg_desc.environment.defaults.sample_count?
2829
2830 A: So that it matches the default sample count in pipeline objects. Even
2831 though it is a bit strange/confusing that offscreen render targets by default
2832 get the same sample count as 'default swapchains', but it's better that
2833 an offscreen render target created with default parameters matches
2834 a pipeline object created with default parameters.
2835
2836 NOTE:
2837
2838 Images with usage SG_USAGE_IMMUTABLE must be fully initialized by
2839 providing a valid .data member which points to initialization data.
2840
2841 ADVANCED TOPIC: Injecting native 3D-API textures:
2842
2843 The following struct members allow to inject your own GL, Metal or D3D11
2844 textures into sokol_gfx:
2845
2846 .gl_textures[SG_NUM_INFLIGHT_FRAMES]
2847 .mtl_textures[SG_NUM_INFLIGHT_FRAMES]
2848 .d3d11_texture
2849 .d3d11_shader_resource_view
2850 .wgpu_texture
2851 .wgpu_texture_view
2852
2853 For GL, you can also specify the texture target or leave it empty to use
2854 the default texture target for the image type (GL_TEXTURE_2D for
2855 SG_IMAGETYPE_2D etc)
2856
2857 For D3D11 and WebGPU, either only provide a texture, or both a texture and
2858 shader-resource-view / texture-view object. If you want to use access the
2859 injected texture in a shader you *must* provide a shader-resource-view.
2860
2861 The same rules apply as for injecting native buffers (see sg_buffer_desc
2862 documentation for more details).
2863*/
2864typedef struct sg_image_desc {
2865 uint32_t _start_canary;
2866 sg_image_type type;
2867 bool render_target;
2868 int width;
2869 int height;
2870 int num_slices;
2871 int num_mipmaps;
2872 sg_usage usage;
2873 sg_pixel_format pixel_format;
2874 int sample_count;
2875 sg_image_data data;
2876 const char* label;
2877 // optionally inject backend-specific resources
2878 uint32_t gl_textures[SG_NUM_INFLIGHT_FRAMES];
2879 uint32_t gl_texture_target;
2880 const void* mtl_textures[SG_NUM_INFLIGHT_FRAMES];
2881 const void* d3d11_texture;
2882 const void* d3d11_shader_resource_view;
2883 const void* wgpu_texture;
2884 const void* wgpu_texture_view;
2885 uint32_t _end_canary;
2886} sg_image_desc;
2887
2888/*
2889 sg_sampler_desc
2890
2891 Creation parameters for sg_sampler objects, used in the sg_make_sampler() call
2892
2893 .min_filter: SG_FILTER_NEAREST
2894 .mag_filter: SG_FILTER_NEAREST
2895 .mipmap_filter SG_FILTER_NONE
2896 .wrap_u: SG_WRAP_REPEAT
2897 .wrap_v: SG_WRAP_REPEAT
2898 .wrap_w: SG_WRAP_REPEAT (only SG_IMAGETYPE_3D)
2899 .min_lod 0.0f
2900 .max_lod FLT_MAX
2901 .border_color SG_BORDERCOLOR_OPAQUE_BLACK
2902 .compare SG_COMPAREFUNC_NEVER
2903 .max_anisotropy 1 (must be 1..16)
2904
2905*/
2906typedef struct sg_sampler_desc {
2907 uint32_t _start_canary;
2908 sg_filter min_filter;
2909 sg_filter mag_filter;
2910 sg_filter mipmap_filter;
2911 sg_wrap wrap_u;
2912 sg_wrap wrap_v;
2913 sg_wrap wrap_w;
2914 float min_lod;
2915 float max_lod;
2916 sg_border_color border_color;
2917 sg_compare_func compare;
2918 uint32_t max_anisotropy;
2919 const char* label;
2920 // optionally inject backend-specific resources
2921 uint32_t gl_sampler;
2922 const void* mtl_sampler;
2923 const void* d3d11_sampler;
2924 const void* wgpu_sampler;
2925 uint32_t _end_canary;
2926} sg_sampler_desc;
2927
2928/*
2929 sg_shader_desc
2930
2931 The structure sg_shader_desc defines all creation parameters for shader
2932 programs, used as input to the sg_make_shader() function:
2933
2934 - reflection information for vertex attributes (vertex shader inputs):
2935 - vertex attribute name (only optionally used by GLES3 and GL)
2936 - a semantic name and index (required for D3D11)
2937 - for each shader-stage (vertex and fragment):
2938 - the shader source or bytecode
2939 - an optional entry function name
2940 - an optional compile target (only for D3D11 when source is provided,
2941 defaults are "vs_4_0" and "ps_4_0")
2942 - reflection info for each uniform block used by the shader stage:
2943 - the size of the uniform block in bytes
2944 - a memory layout hint (native vs std140, only required for GL backends)
2945 - reflection info for each uniform block member (only required for GL backends):
2946 - member name
2947 - member type (SG_UNIFORMTYPE_xxx)
2948 - if the member is an array, the number of array items
2949 - reflection info for textures used in the shader stage:
2950 - the image type (SG_IMAGETYPE_xxx)
2951 - the image-sample type (SG_IMAGESAMPLETYPE_xxx, default is SG_IMAGESAMPLETYPE_FLOAT)
2952 - whether the shader expects a multisampled texture
2953 - reflection info for samplers used in the shader stage:
2954 - the sampler type (SG_SAMPLERTYPE_xxx)
2955 - reflection info for each image-sampler-pair used by the shader:
2956 - the texture slot of the involved texture
2957 - the sampler slot of the involved sampler
2958 - for GLSL only: the name of the combined image-sampler object
2959 - reflection info for each storage-buffer used by the shader:
2960 - whether the storage buffer is readonly (currently this
2961 must be true)
2962
2963 For all GL backends, shader source-code must be provided. For D3D11 and Metal,
2964 either shader source-code or byte-code can be provided.
2965
2966 For D3D11, if source code is provided, the d3dcompiler_47.dll will be loaded
2967 on demand. If this fails, shader creation will fail. When compiling HLSL
2968 source code, you can provide an optional target string via
2969 sg_shader_stage_desc.d3d11_target, the default target is "vs_4_0" for the
2970 vertex shader stage and "ps_4_0" for the pixel shader stage.
2971*/
2972typedef struct sg_shader_attr_desc {
2973 const char* name; // GLSL vertex attribute name (optional)
2974 const char* sem_name; // HLSL semantic name
2975 int sem_index; // HLSL semantic index
2976} sg_shader_attr_desc;
2977
2978typedef struct sg_shader_uniform_desc {
2979 const char* name;
2980 sg_uniform_type type;
2981 int array_count;
2982} sg_shader_uniform_desc;
2983
2984typedef struct sg_shader_uniform_block_desc {
2985 size_t size;
2986 sg_uniform_layout layout;
2987 sg_shader_uniform_desc uniforms[SG_MAX_UB_MEMBERS];
2988} sg_shader_uniform_block_desc;
2989
2990typedef struct sg_shader_storage_buffer_desc {
2991 bool used;
2992 bool readonly;
2993} sg_shader_storage_buffer_desc;
2994
2995typedef struct sg_shader_image_desc {
2996 bool used;
2997 bool multisampled;
2998 sg_image_type image_type;
2999 sg_image_sample_type sample_type;
3000} sg_shader_image_desc;
3001
3002typedef struct sg_shader_sampler_desc {
3003 bool used;
3004 sg_sampler_type sampler_type;
3005} sg_shader_sampler_desc;
3006
3007typedef struct sg_shader_image_sampler_pair_desc {
3008 bool used;
3009 int image_slot;
3010 int sampler_slot;
3011 const char* glsl_name;
3012} sg_shader_image_sampler_pair_desc;
3013
3014typedef struct sg_shader_stage_desc {
3015 const char* source;
3016 sg_range bytecode;
3017 const char* entry;
3018 const char* d3d11_target;
3019 sg_shader_uniform_block_desc uniform_blocks[SG_MAX_SHADERSTAGE_UBS];
3020 sg_shader_storage_buffer_desc storage_buffers[SG_MAX_SHADERSTAGE_STORAGEBUFFERS];
3021 sg_shader_image_desc images[SG_MAX_SHADERSTAGE_IMAGES];
3022 sg_shader_sampler_desc samplers[SG_MAX_SHADERSTAGE_SAMPLERS];
3023 sg_shader_image_sampler_pair_desc image_sampler_pairs[SG_MAX_SHADERSTAGE_IMAGESAMPLERPAIRS];
3024} sg_shader_stage_desc;
3025
3026typedef struct sg_shader_desc {
3027 uint32_t _start_canary;
3028 sg_shader_attr_desc attrs[SG_MAX_VERTEX_ATTRIBUTES];
3029 sg_shader_stage_desc vs;
3030 sg_shader_stage_desc fs;
3031 const char* label;
3032 uint32_t _end_canary;
3033} sg_shader_desc;
3034
3035/*
3036 sg_pipeline_desc
3037
3038 The sg_pipeline_desc struct defines all creation parameters for an
3039 sg_pipeline object, used as argument to the sg_make_pipeline() function:
3040
3041 - the vertex layout for all input vertex buffers
3042 - a shader object
3043 - the 3D primitive type (points, lines, triangles, ...)
3044 - the index type (none, 16- or 32-bit)
3045 - all the fixed-function-pipeline state (depth-, stencil-, blend-state, etc...)
3046
3047 If the vertex data has no gaps between vertex components, you can omit
3048 the .layout.buffers[].stride and layout.attrs[].offset items (leave them
3049 default-initialized to 0), sokol-gfx will then compute the offsets and
3050 strides from the vertex component formats (.layout.attrs[].format).
3051 Please note that ALL vertex attribute offsets must be 0 in order for the
3052 automatic offset computation to kick in.
3053
3054 The default configuration is as follows:
3055
3056 .shader: 0 (must be initialized with a valid sg_shader id!)
3057 .layout:
3058 .buffers[]: vertex buffer layouts
3059 .stride: 0 (if no stride is given it will be computed)
3060 .step_func SG_VERTEXSTEP_PER_VERTEX
3061 .step_rate 1
3062 .attrs[]: vertex attribute declarations
3063 .buffer_index 0 the vertex buffer bind slot
3064 .offset 0 (offsets can be omitted if the vertex layout has no gaps)
3065 .format SG_VERTEXFORMAT_INVALID (must be initialized!)
3066 .depth:
3067 .pixel_format: sg_desc.context.depth_format
3068 .compare: SG_COMPAREFUNC_ALWAYS
3069 .write_enabled: false
3070 .bias: 0.0f
3071 .bias_slope_scale: 0.0f
3072 .bias_clamp: 0.0f
3073 .stencil:
3074 .enabled: false
3075 .front/back:
3076 .compare: SG_COMPAREFUNC_ALWAYS
3077 .fail_op: SG_STENCILOP_KEEP
3078 .depth_fail_op: SG_STENCILOP_KEEP
3079 .pass_op: SG_STENCILOP_KEEP
3080 .read_mask: 0
3081 .write_mask: 0
3082 .ref: 0
3083 .color_count 1
3084