Caffe2 - C++ API
A deep learning, cross platform ML framework
GLAdd.cc
1 
2 #include "../core/GLFilter.h"
3 #include "../core/GLImage.h"
4 #include "../core/ImageAllocator.h"
5 
6 #include "caffe2/core/operator.h"
7 #include "caffe2/core/timer.h"
8 #include <iostream>
9 #include <vector>
10 
11 class GLAdd : public GLFilter {
12  public:
13  binding* inputData[2];
14  binding* outputSize;
15 
16  GLAdd()
17  : GLFilter("GLAdd",
18  vertex_shader,
19  fragment_shader,
20  std::vector<binding*>(
21  {BINDING(outputSize), BINDING(inputData[0]), BINDING(inputData[1])}),
22  {/* no uniform blocks */},
23  {/* no attributes */},
24  {/* no replacements */}) {}
25 
26  template <typename T>
27  void add(const GLImageVector<T>& input_image0,
28  const GLImageVector<T>& input_image1,
29  const GLImageVector<T>& output_image);
30 
31  static const char* fragment_shader;
32 };
33 
34 // MARK: GLSL
35 
36 const char* GLAdd::fragment_shader = R"GLSL(#version 300 es
37 
38 precision mediump float;
39 precision mediump int;
40 
41 in highp vec2 v_texCoord;
42 
43 uniform ivec2 outputSize;
44 
45 TEXTURE_INPUT(inputData[2]);
46 TEXTURE_OUTPUT(0, outputData);
47 
48 void main() {
49  ivec2 texelCoord = ivec2(v_texCoord * vec2(outputSize));
50  vec4 A = TEXTURE_LOAD(inputData[0], texelCoord);
51  vec4 B = TEXTURE_LOAD(inputData[1], texelCoord);
52  vec4 value = A + B;
53  outputData = TEXTURE_STORE(value);
54 }
55 
56 )GLSL";
57 
58 template <typename T>
59 void GLAdd::add(const GLImageVector<T>& input_images0,
60  const GLImageVector<T>& input_images1,
61  const GLImageVector<T>& output_images) {
62  const int num_images = input_images0.size();
63  for (int i = 0; i < num_images; i++) {
64  GLImage<T>* input_image0 = input_images0[i];
65  GLImage<T>* input_image1 = input_images1[i];
66  int input_slices = input_image0->slices;
67  GLImage<T>* output_image = output_images[i];
68  int output_slices = output_image->slices;
69 
70  for (int is = 0; is < input_slices; is++) {
71  std::vector<texture_attachment> input_attachments;
72  input_attachments.push_back({input_image0->textures[is], inputData[0]});
73  input_attachments.push_back({input_image1->textures[is], inputData[1]});
74 
75  run(input_attachments,
76  {output_image->textures.begin() + is, output_image->textures.begin() + is + 1},
77  [&]() { glUniform2i(outputSize->location, output_image->texture_width, output_image->texture_height); },
78  output_image->texture_width,
79  output_image->texture_height);
80  }
81  }
82 }
83 
84 namespace caffe2 {
85 template <typename T>
86 class OpenGLAddOp final : public Operator<CPUContext>, ImageAllocator<T> {
87  public:
88  OpenGLAddOp(const OperatorDef& operator_def, Workspace* ws)
89  : Operator<CPUContext>(operator_def, ws) {
90  OPERATOR_NEEDS_FEATURE(OperatorBase::HasArgument("broadcast") == false,
91  "OpenGLAdd does not support broadcast");
92 
93  OPERATOR_NEEDS_FEATURE(OperatorBase::HasArgument("axis") == false, "OpenGLAdd does not support axis");
94  }
95 
96  bool RunOnDevice() override {
97  const GLImageVector<T>& input0 = Inputs()[0]->template Get<GLImageVector<T>>();
98  const GLImageVector<T>& input1 = Inputs()[1]->template Get<GLImageVector<T>>();
99 
100  CAFFE_ENFORCE_EQ(input0.size(), input1.size());
101 
102  const int num_images = input0.size();
103  const int input_channels = input0.channels();
104  const int input_width = input0.width();
105  const int input_height = input0.height();
106  const int input_tile_x = input0.tile_x();
107  const int input_tile_y = input0.tile_y();
108 
109  CAFFE_ENFORCE_EQ(input1.channels(), input_channels);
110  CAFFE_ENFORCE_EQ(input1.width(), input_width);
111  CAFFE_ENFORCE_EQ(input1.height(), input_height);
112  CAFFE_ENFORCE_EQ(input1.tile_x(), input_tile_x);
113  CAFFE_ENFORCE_EQ(input1.tile_y(), input_tile_y);
114 
115  const int output_channels = input_channels;
116  const int output_width = input_width;
117  const int output_height = input_height;
118  const int output_tile_x = input_tile_x;
119  const int output_tile_y = input_tile_y;
120 
121  int is_last = OperatorBase::GetSingleArgument<int>("is_last", 0);
122 
124  num_images, output_width, output_height, output_channels, output_tile_x, output_tile_y, is_last);
125 
126  if (!_add) {
127  _add.reset(new GLAdd());
128  }
129 
130  _add->add(input0, input1, *output);
131 
132  Outputs()[0]->Reset(output);
133 
134  return true;
135  }
136 
137  private:
138  std::unique_ptr<GLAdd> _add;
139 };
140 
141 REGISTER_CPU_OPERATOR(OpenGLAdd, OpenGLAddOp<float16_t>);
142 OPERATOR_SCHEMA(OpenGLAdd).NumInputs(2).NumOutputs(1);
143 } // namespace caffe2
Definition: GLAdd.cc:11
Workspace is a class that holds all the related objects created during runtime: (1) all blobs...
Definition: workspace.h:47
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...