src/draw_call.c
1#include "alba.h"
2#include "internal.h"
3
4DrawCall *window_create_draw_call(AlbaWindow *window) {
5 DrawCall draw_call = {0};
6 draw_call.buffers_dirty = 1;
7 draw_call.bind_group_dirty = 1;
8 draw_call.new_vertices = alba_create_array(sizeof(AlbaVector), 0);
9 draw_call.new_attributes = alba_create_array(sizeof(AlbaAttribute), 0);
10 draw_call.new_indices = alba_create_array(sizeof(uint32_t), 0);
11 draw_call.new_texts = alba_create_array(sizeof(Text), 0);
12 alba_array_append(&window->draw_calls, &draw_call);
13 return alba_array_last(&window->draw_calls);
14}
15
16void window_set_texture(AlbaWindow *window, const WGPUTexture texture) {
17 DrawCall *draw_call = alba_array_last(&window->draw_calls);
18 if (draw_call->texture_set) {
19 draw_call = window_create_draw_call(window);
20 }
21 draw_call_set_texture(draw_call, texture);
22 draw_call->texture_set = 1;
23}
24
25void window_clear(AlbaWindow *window) {
26 alba_array_clear(&window->draw_calls);
27}
28
29void clear_texture_bind_group(const DrawCall *draw_call) {
30 wgpuBindGroupRelease(draw_call->bind_group);
31}
32
33void draw_call_set_texture(DrawCall *draw_call, const WGPUTexture texture) {
34 if (draw_call->view != NULL) {
35 wgpuTextureViewRelease(draw_call->view);
36 }
37 if (draw_call->texture != NULL) {
38 wgpuTextureDestroy(draw_call->texture);
39 wgpuTextureRelease(draw_call->texture);
40 }
41
42 draw_call->texture = texture;
43 draw_call->view = wgpuTextureCreateView(draw_call->texture, NULL);
44 draw_call->bind_group_dirty = 1;
45}
46
47void draw_call_update_bind_group(const AlbaWindow *window, DrawCall *draw_call) {
48 WGPUBindGroupEntry bind_group_entries[2] = {0};
49
50 // Texture
51 if (draw_call->texture == NULL) {
52 draw_call_set_texture(
53 draw_call,
54 // 1x1 white texture
55 create_texture(
56 window,
57 WGPUTextureUsage_TextureBinding | WGPUTextureUsage_CopyDst,
58 (AlbaVector){1, 1},
59 window->surface_format,
60 1,
61 &(AlbaColor)WHITE
62 )
63 );
64 }
65
66 // @binding(1)
67 bind_group_entries[0].binding = 0; // @group(1) @binding(0)
68 bind_group_entries[0].textureView = draw_call->view;
69
70 // Sampler
71 if (draw_call->sampler == NULL) {
72 WGPUSamplerDescriptor sampler_options = {0};
73 sampler_options.addressModeU = WGPUAddressMode_ClampToEdge;
74 sampler_options.addressModeV = WGPUAddressMode_ClampToEdge;
75 sampler_options.addressModeW = WGPUAddressMode_ClampToEdge;
76 sampler_options.magFilter = WGPUFilterMode_Linear;
77 sampler_options.minFilter = WGPUFilterMode_Linear;
78 sampler_options.mipmapFilter = WGPUMipmapFilterMode_Linear;
79 sampler_options.lodMinClamp = 0;
80 sampler_options.lodMaxClamp = 1;
81 sampler_options.maxAnisotropy = 1;
82 draw_call->sampler = wgpuDeviceCreateSampler(window->device, &sampler_options);
83 }
84
85 // @binding(2)
86 bind_group_entries[1].binding = 1; // @group(1) @binding(1)
87 bind_group_entries[1].sampler = draw_call->sampler;
88
89 WGPUBindGroupDescriptor binding_group_options = {0};
90 binding_group_options.layout = window->texture_bind_group_layout;
91 binding_group_options.entryCount = 2;
92 binding_group_options.entries = bind_group_entries;
93
94 if (draw_call->bind_group != NULL) {
95 wgpuBindGroupRelease(draw_call->bind_group);
96 }
97 draw_call->bind_group = wgpuDeviceCreateBindGroup(window->device, &binding_group_options);
98}
99
100void draw_call_release(const DrawCall *draw_call) {
101 wgpuBufferDestroy(draw_call->vertices);
102 wgpuBufferRelease(draw_call->vertices);
103 alba_array_release(&draw_call->new_vertices);
104
105 wgpuBufferDestroy(draw_call->attributes);
106 wgpuBufferRelease(draw_call->attributes);
107 alba_array_release(&draw_call->new_attributes);
108
109 wgpuBufferDestroy(draw_call->indices);
110 wgpuBufferRelease(draw_call->indices);
111 alba_array_release(&draw_call->new_indices);
112
113 wgpuTextureViewRelease(draw_call->view);
114 wgpuTextureDestroy(draw_call->texture);
115 wgpuTextureRelease(draw_call->texture);
116 wgpuSamplerRelease(draw_call->sampler);
117 wgpuBindGroupRelease(draw_call->bind_group);
118}