Caffe2 - C++ API
A deep learning, cross platform ML framework
GLFilter.h
1 
2 #pragma once
3 
4 #include "GLContext.h"
5 #include "GLTexture.h"
6 #include "arm_neon_support.h"
7 
8 #include <functional>
9 #include <string>
10 #include <vector>
11 
12 #define BINDING(variableName) (variableName = new binding{#variableName})
13 #define ATTRIBUTE(variableName, value) (variableName = new binding{#variableName, value})
14 
15 class GLFilter {
16  protected:
17  const std::string kernel_name;
18  GLuint program = 0;
19  GLuint frameBuffer = 0;
20  static constexpr int kMaxUniformBlocks = 12;
21  GLuint uniformBlock[kMaxUniformBlocks] = {0};
22  GLint blockSize[kMaxUniformBlocks] = {0};
23  bool frame_buffer_initialized = false;
24 
25  // glGetError() can be expensive, we should turn error checking off when we're done with debugging
26 
27  static constexpr bool check_opengl_errors = true;
28 
29 public:
30  typedef std::vector<std::pair<std::string, std::string>> replacements_t;
31 
32  struct binding {
33  const std::string name;
34  GLint location;
35  };
36 
38  const GLTexture* texture;
39  const binding* uniform;
40  };
41 
42  GLFilter(const std::string kernel_name,
43  const std::string vertex_shader,
44  const std::string fragment_shader,
45  const std::vector<binding*> uniforms,
46  const std::vector<binding*> uniform_blocks = {},
47  const std::vector<binding*> attributes = {},
48  const replacements_t& replacements = {});
49 
50  // TODO: The set and reset context need to be commented out for unit testing
51  ~GLFilter() {
52  releaseBuffers();
53  deleteProgram();
54  deleteBindings();
55  }
56 
57  void throwRuntimeError(std::function<void(std::stringstream& errmsg)> error_formatter) const {
58  std::stringstream errmsg;
59  errmsg << kernel_name << ": ";
60  error_formatter(errmsg);
61  throw std::runtime_error(errmsg.str());
62  }
63 
64  void checkGLError(std::function<void(std::stringstream& errmsg)> error_formatter) const {
65  if (check_opengl_errors) {
66  GLenum glError = glGetError();
67  if (glError != GL_NO_ERROR) {
68  throwRuntimeError([&](std::stringstream& errmsg) {
69  error_formatter(errmsg);
70  errmsg << ", " << glError;
71  });
72  }
73  }
74  }
75 
76  template <typename T>
77  void attach_uniform_buffer(const binding* block,
78  GLuint bindingPoint, std::function<void(T*, size_t)> loader);
79 
80  void run(const std::vector<texture_attachment>& input,
81  const std::vector<const GLTexture*>& output,
82  std::function<void(void)> uniforms_initializer,
83  int width,
84  int height);
85 
86  void releaseBuffers();
87  void deleteProgram();
88  void deleteBindings();
89 
90  static const char* vertex_shader;
91 
92  private:
93  const std::vector<binding*> uniforms_;
94  const std::vector<binding*> uniform_blocks_;
95  const std::vector<binding*> attributes_;
96 
97  std::string process_replacements(std::string source, const replacements_t& replacements) const;
98 
99  bool createProgram(const GLchar* vertSource, const GLchar* fragSource, GLuint* program) const;
100 
101  GLint compileShader(GLenum target, GLsizei count, const GLchar** sources, GLuint* shader) const;
102  GLint linkProgram(GLuint program) const;
103  GLint validateProgram(GLuint program) const;
104 };