]> git.tdb.fi Git - libs/gl.git/blob - source/core/module.h
Add tessellation shader support to the engine
[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                 TESS_CONTROL = 1,
107                 TESS_EVAL = 2,
108                 GEOMETRY = 3,
109                 FRAGMENT = 4,
110                 COMPUTE = 5
111         };
112
113         enum StorageClass
114         {
115                 UNIFORM_CONSTANT = 0,
116                 INPUT = 1,
117                 UNIFORM = 2,
118                 OUTPUT = 3,
119                 PUSH_CONSTANT = 9
120         };
121
122         enum BuiltinSemantic
123         {
124                 NOT_BUILTIN = -1,
125                 POSITION = 0,
126                 CLIP_DISTANCE = 3,
127                 LAYER = 9,
128                 FRAG_DEPTH = 22
129         };
130
131         struct Constant;
132         struct Structure;
133         struct Variable;
134
135         struct EntryPoint
136         {
137                 std::string name;
138                 unsigned id = 0;
139                 Stage stage = VERTEX;
140                 std::vector<const Variable *> globals;
141                 LinAl::Vector<unsigned, 3> compute_local_size;
142         };
143
144         struct StructMember
145         {
146                 std::string name;
147                 DataType type = VOID;
148                 const Structure *struct_type = 0;
149                 unsigned offset = 0;
150                 unsigned array_size = 0;
151                 unsigned array_stride = 0;
152                 unsigned matrix_stride = 0;
153                 BuiltinSemantic builtin = NOT_BUILTIN;
154         };
155
156         struct Structure
157         {
158                 std::string name;
159                 unsigned id = 0;
160                 unsigned size = 0;
161                 std::vector<StructMember> members;
162         };
163
164         struct Variable
165         {
166                 std::string name;
167                 unsigned id = 0;
168                 DataType type = VOID;
169                 const Structure *struct_type = 0;
170                 StorageClass storage = static_cast<StorageClass>(-1);
171                 unsigned array_size = 0;
172                 int location = -1;
173                 unsigned descriptor_set = 0;
174                 int binding = -1;
175                 BuiltinSemantic builtin = NOT_BUILTIN;
176
177                 bool operator==(const Variable &) const;
178         };
179
180         struct Constant
181         {
182                 std::string name;
183                 unsigned id = 0;
184                 int constant_id = -1;
185                 DataType type = VOID;
186                 union
187                 {
188                         int i_value = 0;
189                         float f_value;
190                 };
191         };
192
193         struct InstructionBlock
194         {
195                 unsigned id = 0;
196                 bool negate_condition = false;
197                 const Constant *condition = 0;
198                 std::vector<const Variable *> accessed_variables;
199                 std::vector<const InstructionBlock *> successors;
200         };
201
202 private:
203         struct TypeInfo
204         {
205                 DataType type = VOID;
206                 const Structure *struct_type = 0;
207                 unsigned array_size = 0;
208                 unsigned array_stride = 0;
209                 StorageClass storage = static_cast<StorageClass>(-1);
210         };
211
212         struct Reflection
213         {
214                 typedef std::vector<std::uint32_t>::const_iterator CodeIterator;
215
216                 std::map<unsigned, std::string> names;
217                 std::map<unsigned, Constant> constants;
218                 std::map<unsigned, TypeInfo> types;
219                 std::map<unsigned, EntryPoint> entry_points;
220                 std::map<unsigned, Structure> structs;
221                 std::map<unsigned, Variable> variables;
222                 std::map<unsigned, InstructionBlock> blocks;
223                 std::map<unsigned, unsigned> access_chain_bases;
224                 Constant true_condition;
225                 InstructionBlock *current_block = 0;
226
227                 static std::uint32_t get_opcode(std::uint32_t);
228                 static CodeIterator get_op_end(const CodeIterator &);
229                 static std::string read_string(CodeIterator &, const CodeIterator &);
230
231                 void reflect_code(const std::vector<std::uint32_t> &);
232                 void reflect_name(CodeIterator);
233                 void reflect_member_name(CodeIterator);
234                 void reflect_entry_point(CodeIterator);
235                 void reflect_execution_mode(CodeIterator);
236                 void reflect_void_type(CodeIterator);
237                 void reflect_bool_type(CodeIterator);
238                 void reflect_int_type(CodeIterator);
239                 void reflect_float_type(CodeIterator);
240                 void reflect_vector_type(CodeIterator);
241                 void reflect_matrix_type(CodeIterator);
242                 void reflect_image_type(CodeIterator);
243                 void reflect_sampled_image_type(CodeIterator);
244                 void reflect_array_type(CodeIterator);
245                 void reflect_struct_type(CodeIterator);
246                 void reflect_pointer_type(CodeIterator);
247                 void reflect_constant(CodeIterator);
248                 void reflect_variable(CodeIterator);
249                 void reflect_access(CodeIterator);
250                 void reflect_access_chain(CodeIterator);
251                 void reflect_decorate(CodeIterator);
252                 void reflect_member_decorate(CodeIterator);
253                 void reflect_label(CodeIterator);
254                 void reflect_branch(CodeIterator);
255                 void reflect_branch_conditional(CodeIterator);
256         };
257
258         std::vector<std::uint32_t> code;
259         std::vector<EntryPoint> entry_points;
260         std::vector<Structure> structs;
261         std::vector<Variable> variables;
262         std::vector<Constant> spec_constants;
263         std::vector<InstructionBlock> blocks;
264         bool specializable = false;
265
266 public:
267         virtual Format get_format() const { return SPIR_V; }
268
269         /** Loads a SPIR-V binary from a file or other I/O object. */
270         void load_code(IO::Base &);
271 private:
272         virtual void compile(SL::Compiler &);
273         void reflect();
274
275 public:
276         const std::vector<std::uint32_t> &get_code() const { return code; }
277         const std::vector<EntryPoint> &get_entry_points() const { return entry_points; }
278         const std::vector<Variable> &get_variables() const { return variables; }
279         const std::vector<Constant> &get_spec_constants() const { return spec_constants; }
280         const std::vector<InstructionBlock> &get_blocks() const { return blocks; }
281         bool is_specializable() const { return specializable; }
282
283         /** Creates a new module which is a specialized version of this one. */
284         SpirVModule *specialize(const std::map<std::string, int> &) const;
285
286 private:
287         std::vector<const InstructionBlock *> collect_visited_blocks(const std::map<unsigned, int> &) const;
288         void collect_visited_blocks(unsigned, std::vector<std::uint8_t> &) const;
289
290 public:
291         void set_debug_name(const std::string &n) { SpirVModuleBackend::set_debug_name(n); }
292 };
293
294 } // namespace GL
295 } // namespace Msp
296
297 #endif