summaryrefslogtreecommitdiff
path: root/workspaces/main/shaders/cnn/cnn_conv5x5.wgsl
blob: 5570589a9150666475fcb40cf905ad25b7c2438b (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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// 5×5 variant for 7→4 channels (RGBD output)
// Assumes 'tex' is already normalized to [-1,1]
// UV coordinates remain in [0,1] and are normalized internally
// weights: array<array<f32, 8>, 100> (25 positions × 4 channels, each with 7 weights + bias)
fn cnn_conv5x5_7to4(
  tex: texture_2d<f32>,
  samp: sampler,
  uv: vec2<f32>,
  resolution: vec2<f32>,
  gray: f32,
  weights: array<array<f32, 8>, 100>
) -> vec4<f32> {
  let step = 1.0 / resolution;
  let uv_norm = (uv - 0.5) * 2.0;

  var sum = vec4<f32>(0.0);
  var pos = 0;

  for (var dy = -2; dy <= 2; dy++) {
    for (var dx = -2; dx <= 2; dx++) {
      let offset = vec2<f32>(f32(dx), f32(dy)) * step;
      let rgbd = textureSample(tex, samp, uv + offset);  // Already in [-1,1]

      let inputs = array<f32, 7>(
        rgbd.r, rgbd.g, rgbd.b, rgbd.a,
        uv_norm.x, uv_norm.y, gray
      );

      for (var out_c = 0; out_c < 4; out_c++) {
        let idx = pos * 4 + out_c;
        var channel_sum = weights[idx][7];
        for (var in_c = 0; in_c < 7; in_c++) {
          channel_sum += weights[idx][in_c] * inputs[in_c];
        }
        sum[out_c] += channel_sum;
      }
      pos++;
    }
  }

  return sum;
}

// 5×5 variant for 7→1 channel (scalar output)
// Assumes 'tex' is already normalized to [-1,1]
// UV coordinates remain in [0,1] and are normalized internally
// weights: array<array<f32, 8>, 25> (25 positions, each with 7 weights + bias)
fn cnn_conv5x5_7to1(
  tex: texture_2d<f32>,
  samp: sampler,
  uv: vec2<f32>,
  resolution: vec2<f32>,
  gray: f32,
  weights: array<array<f32, 8>, 25>
) -> f32 {
  let step = 1.0 / resolution;
  let uv_norm = (uv - 0.5) * 2.0;

  var sum = 0.0;
  var pos = 0;

  for (var dy = -2; dy <= 2; dy++) {
    for (var dx = -2; dx <= 2; dx++) {
      let offset = vec2<f32>(f32(dx), f32(dy)) * step;
      let rgbd = textureSample(tex, samp, uv + offset);  // Already in [-1,1]

      sum += weights[pos][0] * rgbd.r;
      sum += weights[pos][1] * rgbd.g;
      sum += weights[pos][2] * rgbd.b;
      sum += weights[pos][3] * rgbd.a;
      sum += weights[pos][4] * uv_norm.x;
      sum += weights[pos][5] * uv_norm.y;
      sum += weights[pos][6] * gray;
      sum += weights[pos][7];  // Bias

      pos++;
    }
  }

  return sum;  // Output in [-1,1]
}

// Source layer: 7→4 channels (RGBD output)
// Normalizes [0,1] input to [-1,1] internally
fn cnn_conv5x5_7to4_src(
  tex: texture_2d<f32>,
  samp: sampler,
  uv: vec2<f32>,
  resolution: vec2<f32>,
  weights: array<array<f32, 8>, 100>
) -> vec4<f32> {
  let step = 1.0 / resolution;

  let original = (textureSample(tex, samp, uv) - 0.5) * 2.0;
  let gray = dot(original.rgb, vec3<f32>(0.2126, 0.7152, 0.0722));
  let uv_norm = (uv - 0.5) * 2.0;

  var sum = vec4<f32>(0.0);
  var pos = 0;

  for (var dy = -2; dy <= 2; dy++) {
    for (var dx = -2; dx <= 2; dx++) {
      let offset = vec2<f32>(f32(dx), f32(dy)) * step;
      let rgbd = (textureSample(tex, samp, uv + offset) - 0.5) * 2.0;

      let inputs = array<f32, 7>(
        rgbd.r, rgbd.g, rgbd.b, rgbd.a,
        uv_norm.x, uv_norm.y, gray
      );

      for (var out_c = 0; out_c < 4; out_c++) {
        let idx = pos * 4 + out_c;
        var channel_sum = weights[idx][7];
        for (var in_c = 0; in_c < 7; in_c++) {
          channel_sum += weights[idx][in_c] * inputs[in_c];
        }
        sum[out_c] += channel_sum;
      }
      pos++;
    }
  }

  return sum;
}