]> git.tdb.fi Git - libs/gl.git/blob - source/core/module.h
Support compute shaders and compute operations
[libs/gl.git] / source / core / module.h
1 #ifndef MSP_GL_MODULE_H_
2 #define MSP_GL_MODULE_H_
3
4 #include <map>
5 #include <string>
6 #include <vector>
7 #include <msp/io/base.h>
8 #include "datatype.h"
9 #include "module_backend.h"
10 #include "glsl/compiler.h"
11 #include "glsl/sourcemap.h"
12
13 namespace Msp {
14 namespace GL {
15
16 class invalid_module: public std::runtime_error
17 {
18 public:
19         invalid_module(const std::string &w): runtime_error(w) { }
20         virtual ~invalid_module() throw() { }
21 };
22
23 class Resources;
24
25 /**
26 Base class for shader modules.  Internal representation depends on the
27 concrete type.
28
29 Modules can be loaded from files.
30
31 Applications normally use the Program class to access shaders.
32 */
33 class Module
34 {
35 public:
36         enum Format
37         {
38                 GLSL,
39                 SPIR_V
40         };
41
42 protected:
43         Module() = default;
44 public:
45         virtual ~Module() = default;
46
47         virtual Format get_format() const = 0;
48
49         /** Sets the module's content from GLSL source code. */
50         void set_source(const std::string &);
51
52         /** Loads GLSL source from a file or other I/O object.  Any import
53         statements are resolved using res. */
54         void load_source(IO::Base &, Resources *res, const std::string &name);
55
56         /** Loads GLSL source from a file or other I/O object.  Only builtin
57         shader fragments can be imported. */
58         void load_source(IO::Base &, const std::string &);
59
60 private:
61         virtual void compile(SL::Compiler &) = 0;
62
63         SL::Features create_features() const;
64
65 public:
66         virtual void set_debug_name(const std::string &) { }
67 };
68
69 /**
70 A shader module in GLSL source code format.
71 */
72 class GlslModule: public Module
73 {
74 private:
75         std::string prepared_source;
76         SL::SourceMap source_map;
77
78 public:
79         virtual Format get_format() const { return GLSL; }
80
81 private:
82         virtual void compile(SL::Compiler &);
83
84 public:
85         const std::string &get_prepared_source() const { return prepared_source; }
86         const SL::SourceMap &get_source_map() const { return source_map; }
87 };
88
89 /**
90 A shader module in SPIR-V binary format.
91
92 When the module's contents are set from GLSL source, it will be automatically
93 compiled to SPIR-V.  Pre-compiled SPIR-V modules can also be loaded.
94
95 Afterwards reflection data is available, providing information about variables
96 forming the module's interface.
97 */
98 class SpirVModule: public Module, public SpirVModuleBackend
99 {
100         friend SpirVModuleBackend;
101
102 public:
103         enum Stage
104         {
105                 VERTEX = 0,
106                 GEOMETRY = 3,
107                 FRAGMENT = 4,
108                 COMPUTE = 5
109         };
110
111         enum StorageClass
112         {
113                 UNIFORM_CONSTANT = 0,
114                 INPUT = 1,
115                 UNIFORM = 2,
116                 OUTPUT = 3,
117                 PUSH_CONSTANT = 9
118         };
119
120         enum BuiltinSemantic
121         {
122                 NOT_BUILTIN = -1,
123                 POSITION = 0,
124                 CLIP_DISTANCE = 3,
125                 LAYER = 9,
126                 FRAG_DEPTH = 22
127         };
128
129         struct Constant;
130         struct Structure;
131         struct Variable;
132
133         struct EntryPoint
134         {
135                 std::string name;
136                 unsigned id = 0;
137                 Stage stage = VERTEX;
138                 std::vector<const Variable *> globals;
139                 LinAl::Vector<unsigned, 3> compute_local_size;
140         };
141
142         struct StructMember
143         {
144                 std::string name;
145                 DataType type = VOID;
146                 const Structure *struct_type = 0;
147                 unsigned offset = 0;
148                 unsigned array_size = 0;
149                 unsigned array_stride = 0;
150                 unsigned matrix_stride = 0;
151                 BuiltinSemantic builtin = NOT_BUILTIN;
152         };
153
154         struct Structure
155         {
156                 std::string name;
157                 unsigned id = 0;
158                 unsigned size = 0;
159                 std::vector<StructMember> members;
160         };
161
162         struct Variable
163         {
164                 std::string name;
165                 unsigned id = 0;
166                 DataType type = VOID;
167                 const Structure *struct_type = 0;
168                 StorageClass storage = static_cast<StorageClass>(-1);
169                 unsigned array_size = 0;
170                 int location = -1;
171                 unsigned descriptor_set = 0;
172                 int binding = -1;
173                 BuiltinSemantic builtin = NOT_BUILTIN;
174
175                 bool operator==(const Variable &) const;
176         };
177
178         struct Constant
179         {
180                 std::string name;
181                 unsigned id = 0;
182                 int constant_id = -1;
183                 DataType type = VOID;
184                 union
185                 {
186                         int i_value = 0;
187                         float f_value;
188                 };
189         };
190
191         struct InstructionBlock
192         {
193                 unsigned id = 0;
194                 bool negate_condition = false;
195                 const Constant *condition = 0;
196                 std::vector<const Variable *> accessed_variables;
197                 std::vector<const InstructionBlock *> successors;
198         };
199
200 private:
201         struct TypeInfo
202         {
203                 DataType type = VOID;
204                 const Structure *struct_type = 0;
205                 unsigned array_size = 0;
206                 unsigned array_stride = 0;
207                 StorageClass storage = static_cast<StorageClass>(-1);
208         };
209
210         struct Reflection
211         {
212                 typedef std::vector<std::uint32_t>::const_iterator CodeIterator;
213
214                 std::map<unsigned, std::string> names;
215                 std::map<unsigned, Constant> constants;
216                 std::map<unsigned, TypeInfo> types;
217                 std::map<unsigned, EntryPoint> entry_points;
218                 std::map<unsigned, Structure> structs;
219                 std::map<unsigned, Variable> variables;
220                 std::map<unsigned, InstructionBlock> blocks;
221                 std::map<unsigned, unsigned> access_chain_bases;
222                 Constant true_condition;
223                 InstructionBlock *current_block = 0;
224
225                 static std::uint32_t get_opcode(std::uint32_t);
226                 static CodeIterator get_op_end(const CodeIterator &);
227                 static std::string read_string(CodeIterator &, const CodeIterator &);
228
229                 void reflect_code(const std::vector<std::uint32_t> &);
230                 void reflect_name(CodeIterator);
231                 void reflect_member_name(CodeIterator);
232                 void reflect_entry_point(CodeIterator);
233                 void reflect_execution_mode(CodeIterator);
234                 void reflect_void_type(CodeIterator);
235                 void reflect_bool_type(CodeIterator);
236                 void reflect_int_type(CodeIterator);
237                 void reflect_float_type(CodeIterator);
238                 void reflect_vector_type(CodeIterator);
239                 void reflect_matrix_type(CodeIterator);
240                 void reflect_image_type(CodeIterator);
241                 void reflect_sampled_image_type(CodeIterator);
242                 void reflect_array_type(CodeIterator);
243                 void reflect_struct_type(CodeIterator);
244                 void reflect_pointer_type(CodeIterator);
245                 void reflect_constant(CodeIterator);
246                 void reflect_variable(CodeIterator);
247                 void reflect_access(CodeIterator);
248                 void reflect_access_chain(CodeIterator);
249                 void reflect_decorate(CodeIterator);
250                 void reflect_member_decorate(CodeIterator);
251                 void reflect_label(CodeIterator);
252                 void reflect_branch(CodeIterator);
253                 void reflect_branch_conditional(CodeIterator);
254         };
255
256         std::vector<std::uint32_t> code;
257         std::vector<EntryPoint> entry_points;
258         std::vector<Structure> structs;
259         std::vector<Variable> variables;
260         std::vector<Constant> spec_constants;
261         std::vector<InstructionBlock> blocks;
262         bool specializable = false;
263
264 public:
265         virtual Format get_format() const { return SPIR_V; }
266
267         /** Loads a SPIR-V binary from a file or other I/O object. */
268         void load_code(IO::Base &);
269 private:
270         virtual void compile(SL::Compiler &);
271         void reflect();
272
273 public:
274         const std::vector<std::uint32_t> &get_code() const { return code; }
275         const std::vector<EntryPoint> &get_entry_points() const { return entry_points; }
276         const std::vector<Variable> &get_variables() const { return variables; }
277         const std::vector<Constant> &get_spec_constants() const { return spec_constants; }
278         const std::vector<InstructionBlock> &get_blocks() const { return blocks; }
279         bool is_specializable() const { return specializable; }
280
281         /** Creates a new module which is a specialized version of this one. */
282         SpirVModule *specialize(const std::map<std::string, int> &) const;
283
284 private:
285         std::vector<const InstructionBlock *> collect_visited_blocks(const std::map<unsigned, int> &) const;
286         void collect_visited_blocks(unsigned, std::vector<std::uint8_t> &) const;
287
288 public:
289         void set_debug_name(const std::string &n) { SpirVModuleBackend::set_debug_name(n); }
290 };
291
292 } // namespace GL
293 } // namespace Msp
294
295 #endif