Partial: remove pipelines - pipeline layout
Francesco Pasa 10 months ago
Francesco Pasa 10 months ago
src/window.c M +108 -100
60
61
62 // TODO: reorganize code
63-WGPUPipelineLayout configure_resources(const AlbaWindow* window, DrawCall* data)
63+WGPUPipelineLayout configure_bind_group_layout(const AlbaWindow* window)
64 {
65- WGPUBindGroupLayoutEntry bind_group_layout_entries[3] = {0};
65+ WGPUBindGroupLayout bind_groups[2];
66+
67+ // @group(0) - Uniforms (scale)
68+ // --------------------------------------------
69+ WGPUBindGroupLayoutEntry uniforms_bind_group_entries[1] = {0};
70
71- // Uniform (scale)
71 // @binding(0)
72- bind_group_layout_entries[0].binding = 0;
73- bind_group_layout_entries[0].visibility = WGPUShaderStage_Vertex;
74- bind_group_layout_entries[0].buffer.type = WGPUBufferBindingType_Uniform;
72+ uniforms_bind_group_entries[0].binding = 0;
73+ uniforms_bind_group_entries[0].visibility = WGPUShaderStage_Vertex;
74+ uniforms_bind_group_entries[0].buffer.type = WGPUBufferBindingType_Uniform;
75
76- // Texture
77- // @binding(1)
78- bind_group_layout_entries[1].binding = 1;
79- bind_group_layout_entries[1].visibility = WGPUShaderStage_Fragment;
80- bind_group_layout_entries[1].texture.sampleType = WGPUTextureSampleType_Float;
81- bind_group_layout_entries[1].texture.viewDimension = WGPUTextureViewDimension_2D;
82-
83- // Sampler
84- // @binding(2)
85- bind_group_layout_entries[2].binding = 2;
86- bind_group_layout_entries[2].visibility = WGPUShaderStage_Fragment;
87- bind_group_layout_entries[2].sampler.type = WGPUSamplerBindingType_Filtering;
88-
89- WGPUBindGroupLayoutDescriptor bind_group_layout_options = {0};
90- bind_group_layout_options.entryCount = 3;
91- bind_group_layout_options.entries = bind_group_layout_entries;
92- const WGPUBindGroupLayout bind_group_layout = wgpuDeviceCreateBindGroupLayout(
93- window->device, &bind_group_layout_options);
94-
95- // --------------------------
96- WGPUBindGroupEntry bind_group_entries[3] = {0};
97-
98- // Uniform (scale)
99- WGPUBufferDescriptor uniform_options = {0};
100- uniform_options.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform;
101- uniform_options.size = 2 * sizeof(float);
102- if (data->uniforms == NULL)
103- {
104- data->uniforms = wgpuDeviceCreateBuffer(window->device, &uniform_options);
105- }
76+ WGPUBindGroupLayoutDescriptor uniforms_bind_group_options = {0};
77+ uniforms_bind_group_options.entryCount = 1;
78+ uniforms_bind_group_options.entries = uniforms_bind_group_entries;
79+ bind_groups[0] = wgpuDeviceCreateBindGroupLayout(window->device, &uniforms_bind_group_options);
80
81- // @binding(0)
82- bind_group_entries[0].binding = 0;
83- bind_group_entries[0].buffer = data->uniforms;
84- bind_group_entries[0].size = uniform_options.size;
81+ // @group(1) - Texture & sampler
82+ // --------------------------------------------
83+ WGPUBindGroupLayoutEntry texture_bind_group_entries[2] = {0};
84
85- // Texture
86- if (data->texture == NULL)
87- {
88- // 1x1 transparent texture
89- data->texture = create_texture(
90- window,
91- WGPUTextureUsage_TextureBinding | WGPUTextureUsage_CopyDst,
92- (AlbaVector){1, 1},
93- WGPUTextureFormat_RGBA8UnormSrgb, 1,
94- &(AlbaColor)WHITE
95- );
96- }
85+ // @binding(0)
86+ texture_bind_group_entries[0].binding = 0;
87+ texture_bind_group_entries[0].visibility = WGPUShaderStage_Fragment;
88+ texture_bind_group_entries[0].texture.sampleType = WGPUTextureSampleType_Float;
89+ texture_bind_group_entries[0].texture.viewDimension = WGPUTextureViewDimension_2D;
90 // @binding(1)
91- bind_group_entries[1].binding = 1;
92- bind_group_entries[1].textureView = wgpuTextureCreateView(data->texture, NULL);
93-
94- // Sampler
95- WGPUSamplerDescriptor sampler_options = {0};
96- sampler_options.addressModeU = WGPUAddressMode_ClampToEdge;
97- sampler_options.addressModeV = WGPUAddressMode_ClampToEdge;
98- sampler_options.addressModeW = WGPUAddressMode_ClampToEdge;
99- sampler_options.magFilter = WGPUFilterMode_Linear;
100- sampler_options.minFilter = WGPUFilterMode_Linear;
101- sampler_options.mipmapFilter = WGPUMipmapFilterMode_Linear;
102- sampler_options.lodMinClamp = 0;
103- sampler_options.lodMaxClamp = 1;
104- sampler_options.maxAnisotropy = 1;
105-
106- // @binding(2)
107- bind_group_entries[2].binding = 2;
108- // TODO: free previous
109- bind_group_entries[2].sampler = wgpuDeviceCreateSampler(window->device, &sampler_options);
110-
111- WGPUBindGroupDescriptor binding_group_options = {0};
112- binding_group_options.layout = bind_group_layout;
113- binding_group_options.entryCount = 3;
114- binding_group_options.entries = bind_group_entries;
115-
116- // TODO: free previous
117- data->bind_group = wgpuDeviceCreateBindGroup(window->device, &binding_group_options);
118-
119- // A pipeline can have multiple bind groups
91+ texture_bind_group_entries[1].binding = 1;
92+ texture_bind_group_entries[1].visibility = WGPUShaderStage_Fragment;
93+ texture_bind_group_entries[1].sampler.type = WGPUSamplerBindingType_Filtering;
94+
95+ WGPUBindGroupLayoutDescriptor texture_bind_group_options = {0};
96+ texture_bind_group_options.entryCount = 2;
97+ texture_bind_group_options.entries = texture_bind_group_entries;
98+ bind_groups[1] = wgpuDeviceCreateBindGroupLayout(window->device, &texture_bind_group_options);
99+
100+ // Pipeline layout
101+ // --------------------------------------------
102 WGPUPipelineLayoutDescriptor pipeline_layout_options = {0};
103- pipeline_layout_options.bindGroupLayoutCount = 1;
104- pipeline_layout_options.bindGroupLayouts = &bind_group_layout;
105- // TODO: free previous
103+ pipeline_layout_options.bindGroupLayoutCount = 2;
104+ pipeline_layout_options.bindGroupLayouts = bind_groups;
105 const WGPUPipelineLayout pipeline_layout = wgpuDeviceCreatePipelineLayout(
106 window->device, &pipeline_layout_options);
106
107- wgpuBindGroupLayoutRelease(bind_group_layout);
107+ wgpuBindGroupLayoutRelease(bind_groups[0]);
108+ wgpuBindGroupLayoutRelease(bind_groups[1]);
109
110 return pipeline_layout;
111+
112+ // // --------------------------
113+ // WGPUBindGroupEntry bind_group_entries[3] = {0};
114+ //
115+ // // Uniform (scale)
116+ // WGPUBufferDescriptor uniform_options = {0};
117+ // uniform_options.usage = WGPUBufferUsage_CopyDst | WGPUBufferUsage_Uniform;
118+ // uniform_options.size = 2 * sizeof(float);
119+ // if (data->uniforms == NULL)
120+ // {
121+ // data->uniforms = wgpuDeviceCreateBuffer(window->device, &uniform_options);
122+ // }
123+ //
124+ // // @binding(0)
125+ // bind_group_entries[0].binding = 0;
126+ // bind_group_entries[0].buffer = data->uniforms;
127+ // bind_group_entries[0].size = uniform_options.size;
128+ //
129+ // // Texture
130+ // if (data->texture == NULL)
131+ // {
132+ // // 1x1 transparent texture
133+ // data->texture = create_texture(
134+ // window,
135+ // WGPUTextureUsage_TextureBinding | WGPUTextureUsage_CopyDst,
136+ // (AlbaVector){1, 1},
137+ // WGPUTextureFormat_RGBA8UnormSrgb, 1,
138+ // &(AlbaColor)WHITE
139+ // );
140+ // }
141+ // // @binding(1)
142+ // bind_group_entries[1].binding = 1;
143+ // bind_group_entries[1].textureView = wgpuTextureCreateView(data->texture, NULL);
144+ //
145+ // // Sampler
146+ // WGPUSamplerDescriptor sampler_options = {0};
147+ // sampler_options.addressModeU = WGPUAddressMode_ClampToEdge;
148+ // sampler_options.addressModeV = WGPUAddressMode_ClampToEdge;
149+ // sampler_options.addressModeW = WGPUAddressMode_ClampToEdge;
150+ // sampler_options.magFilter = WGPUFilterMode_Linear;
151+ // sampler_options.minFilter = WGPUFilterMode_Linear;
152+ // sampler_options.mipmapFilter = WGPUMipmapFilterMode_Linear;
153+ // sampler_options.lodMinClamp = 0;
154+ // sampler_options.lodMaxClamp = 1;
155+ // sampler_options.maxAnisotropy = 1;
156+ //
157+ // // @binding(2)
158+ // bind_group_entries[2].binding = 2;
159+ // // TODO: free previous
160+ // bind_group_entries[2].sampler = wgpuDeviceCreateSampler(window->device, &sampler_options);
161+ //
162+ // WGPUBindGroupDescriptor binding_group_options = {0};
163+ // binding_group_options.layout = bind_group_layout;
164+ // binding_group_options.entryCount = 3;
165+ // binding_group_options.entries = bind_group_entries;
166+ //
167+ // // TODO: free previous
168+ // data->bind_group = wgpuDeviceCreateBindGroup(window->device, &binding_group_options);
169 }
170
171 void configure_surface(AlbaWindow* window)
181 window->size = (AlbaVector){width, height};
182 window->scale = (AlbaVector){width / (2 * x_scale), height / (2 * y_scale)};
181
182- // TODO: callback when scaling changes
182+ // TODO: callback when scaling changes (window changes monitor)
183 // Update uniforms
184- wgpuQueueWriteBuffer(window->queue, window->layers[0].drawing.uniforms, 0, &window->scale, sizeof(AlbaVector));
185- wgpuQueueWriteBuffer(window->queue, window->layers[0].text.uniforms, 0, &window->scale, sizeof(AlbaVector));
184+ wgpuQueueWriteBuffer(window->queue, window->uniforms, 0, &window->scale, sizeof(AlbaVector));
185
186 const WGPUTextureFormat format = wgpuSurfaceGetPreferredFormat(window->surface, window->adapter);
187
197 wgpuSurfaceConfigure(window->surface, &surface_options);
198 }
199
200-
200 void configure_pipeline(AlbaWindow* window)
201 {
202+ // Load shaders
203+ // --------------------------------------------
204 WGPUShaderModuleWGSLDescriptor shader_options = {0};
205 shader_options.chain.sType = WGPUSType_ShaderModuleWGSLDescriptor;
206 shader_options.code = _binary_shaders_wgsl_start;
211 window->shaders = wgpuDeviceCreateShaderModule(window->device, &shader_loader_options);
211
212 // Configure render pipeline
213+ // --------------------------------------------
214 WGPURenderPipelineDescriptor pipleine_options = {0};
215 // Rendering settings
216 pipleine_options.primitive.topology = WGPUPrimitiveTopology_TriangleList;
281 fragment_state.targets = &color_state;
282 pipleine_options.fragment = &fragment_state;
283
284- // Configure resources for drawing pass
285- pipleine_options.layout = configure_resources(window, &window->layers[0].drawing);
286- window->layers[0].drawing.pipeline = wgpuDeviceCreateRenderPipeline(window->device, &pipleine_options);
287-
288- // Configure resources for text pass
289- pipleine_options.layout = configure_resources(window, &window->layers[0].text);
290- window->layers[0].text.pipeline = wgpuDeviceCreateRenderPipeline(window->device, &pipleine_options);
284+ // Configure bind groups layout
285+ // --------------------------------------------
286+ pipleine_options.layout = configure_bind_group_layout(window);
287+ window->pipeline = wgpuDeviceCreateRenderPipeline(window->device, &pipleine_options);
288
289 wgpuPipelineLayoutRelease(pipleine_options.layout);
290 }
314 memset(window, 0, sizeof(AlbaWindow));
315
316 window->options = *options;
317- window->layers = create_layer();
316
317 // GLFW window
318 glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
356 configure_pipeline(window);
357 configure_surface(window);
358
359+ window->draw_calls = alba_create_array(sizeof(DrawCall), 0);
360+
361 return window;
362 }
363
375 {
376 for (uint64_t i = 0; i < window->draw_calls.length; i++)
377 {
378- draw_call_release(&window->draw_calls.data[i]);
378+ draw_call_release(window->draw_calls.data + i);
379 }
380 alba_array_release(&window->draw_calls);
381
435 wgpuRenderPassEncoderSetPipeline(render_pass, window->pipeline);
436 for (uint64_t i = 0; i < window->draw_calls.length; i++)
437 {
438- DrawCall* draw_call = &window->draw_calls.data[i];
438+ DrawCall* draw_call = window->draw_calls.data + i;
439
440 wgpuRenderPassEncoderSetBindGroup(render_pass, 0, draw_call->bind_group, 0, NULL);
441
523 render_pass_attachment_options.view = render_target_view;
524 render_pass_attachment_options.loadOp = WGPULoadOp_Clear;
525 render_pass_attachment_options.storeOp = WGPUStoreOp_Store;
526- render_pass_attachment_options.resolveTarget = frame;
526+ render_pass_attachment_options.resolveTarget = frame_view;
527 copy_color(window->options.clear_color, &render_pass_attachment_options.clearValue);
528
529 WGPURenderPassDescriptor render_pass_options = {0};