1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
// This file is part of the 64k demo project.
// It implements helper functions for post-processing effects.
#include "../demo_effects.h"
#include "gpu/gpu.h"
#include <cstring>
// Helper to create a standard post-processing pipeline
WGPURenderPipeline create_post_process_pipeline(WGPUDevice device,
WGPUTextureFormat format,
const char* shader_code) {
WGPUShaderModuleDescriptor shader_desc = {};
WGPUShaderSourceWGSL wgsl_src = {};
wgsl_src.chain.sType = WGPUSType_ShaderSourceWGSL;
wgsl_src.code = str_view(shader_code);
shader_desc.nextInChain = &wgsl_src.chain;
WGPUShaderModule shader_module =
wgpuDeviceCreateShaderModule(device, &shader_desc);
WGPUBindGroupLayoutEntry bgl_entries[3] = {};
bgl_entries[0].binding = 0;
bgl_entries[0].visibility = WGPUShaderStage_Fragment;
bgl_entries[0].sampler.type = WGPUSamplerBindingType_Filtering;
bgl_entries[1].binding = 1;
bgl_entries[1].visibility = WGPUShaderStage_Fragment;
bgl_entries[1].texture.sampleType = WGPUTextureSampleType_Float;
bgl_entries[1].texture.viewDimension = WGPUTextureViewDimension_2D;
bgl_entries[2].binding = 2;
bgl_entries[2].visibility = WGPUShaderStage_Fragment;
bgl_entries[2].buffer.type = WGPUBufferBindingType_Uniform;
WGPUBindGroupLayoutDescriptor bgl_desc = {};
bgl_desc.entryCount = 3;
bgl_desc.entries = bgl_entries;
WGPUBindGroupLayout bgl = wgpuDeviceCreateBindGroupLayout(device, &bgl_desc);
WGPUPipelineLayoutDescriptor pl_desc = {};
pl_desc.bindGroupLayoutCount = 1;
pl_desc.bindGroupLayouts = &bgl;
WGPUPipelineLayout pl = wgpuDeviceCreatePipelineLayout(device, &pl_desc);
WGPUColorTargetState color_target = {};
color_target.format = format;
color_target.writeMask = WGPUColorWriteMask_All;
WGPUFragmentState fragment_state = {};
fragment_state.module = shader_module;
fragment_state.entryPoint = str_view("fs_main");
fragment_state.targetCount = 1;
fragment_state.targets = &color_target;
WGPURenderPipelineDescriptor pipeline_desc = {};
pipeline_desc.layout = pl;
pipeline_desc.vertex.module = shader_module;
pipeline_desc.vertex.entryPoint = str_view("vs_main");
pipeline_desc.fragment = &fragment_state;
pipeline_desc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
pipeline_desc.multisample.count = 1;
pipeline_desc.multisample.mask = 0xFFFFFFFF;
return wgpuDeviceCreateRenderPipeline(device, &pipeline_desc);
}
// --- PostProcess Implementation Helper ---
void pp_update_bind_group(WGPUDevice device, WGPURenderPipeline pipeline,
WGPUBindGroup* bind_group, WGPUTextureView input_view,
GpuBuffer uniforms) {
if (*bind_group)
wgpuBindGroupRelease(*bind_group);
WGPUBindGroupLayout bgl = wgpuRenderPipelineGetBindGroupLayout(pipeline, 0);
WGPUSamplerDescriptor sd = {};
sd.magFilter = WGPUFilterMode_Linear;
sd.minFilter = WGPUFilterMode_Linear;
sd.maxAnisotropy = 1;
WGPUSampler sampler = wgpuDeviceCreateSampler(device, &sd);
WGPUBindGroupEntry bge[3] = {};
bge[0].binding = 0;
bge[0].sampler = sampler;
bge[1].binding = 1;
bge[1].textureView = input_view;
bge[2].binding = 2;
bge[2].buffer = uniforms.buffer;
bge[2].size = uniforms.size;
WGPUBindGroupDescriptor bgd = {
.layout = bgl, .entryCount = 3, .entries = bge};
*bind_group = wgpuDeviceCreateBindGroup(device, &bgd);
}
|