summaryrefslogtreecommitdiff
path: root/src/gpu/effects/post_process_helper.cc
blob: db89d77f4acc8a4e01d4fc614ec838294586983a (plain)
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);
}