]> git.tdb.fi Git - libs/gl.git/blob - source/core/module.h
Create specialized versions of SPIR-V modules with default spec values
[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
66 /**
67 A shader module in GLSL source code format.
68 */
69 class GlslModule: public Module
70 {
71 private:
72         std::string prepared_source;
73         SL::SourceMap source_map;
74
75 public:
76         virtual Format get_format() const { return GLSL; }
77
78 private:
79         virtual void compile(SL::Compiler &);
80
81 public:
82         const std::string &get_prepared_source() const { return prepared_source; }
83         const SL::SourceMap &get_source_map() const { return source_map; }
84 };
85
86 /**
87 A shader module in SPIR-V binary format.
88
89 When the module's contents are set from GLSL source, it will be automatically
90 compiled to SPIR-V.  Pre-compiled SPIR-V modules can also be loaded.
91
92 Afterwards reflection data is available, providing information about variables
93 forming the module's interface.
94 */
95 class SpirVModule: public Module, public SpirVModuleBackend
96 {
97         friend SpirVModuleBackend;
98
99 public:
100         enum Stage
101         {
102                 VERTEX = 0,
103                 GEOMETRY = 3,
104                 FRAGMENT = 4
105         };
106
107         enum StorageClass
108         {
109                 UNIFORM_CONSTANT = 0,
110                 INPUT = 1,
111                 UNIFORM = 2,
112                 OUTPUT = 3,
113                 PUSH_CONSTANT = 9
114         };
115
116         enum BuiltinSemantic
117         {
118                 NOT_BUILTIN = -1,
119                 POSITION = 0,
120                 CLIP_DISTANCE = 3,
121                 LAYER = 9,
122                 FRAG_DEPTH = 22
123         };
124
125         struct Constant;
126         struct Structure;
127         struct Variable;
128
129         struct EntryPoint
130         {
131                 std::string name;
132                 unsigned id = 0;
133                 Stage stage = VERTEX;
134                 std::vector<const Variable *> globals;
135         };
136
137         struct StructMember
138         {
139                 std::string name;
140                 DataType type = VOID;
141                 const Structure *struct_type = 0;
142                 unsigned offset = 0;
143                 unsigned array_size = 0;
144                 unsigned array_stride = 0;
145                 unsigned matrix_stride = 0;
146                 BuiltinSemantic builtin = NOT_BUILTIN;
147         };
148
149         struct Structure
150         {
151                 std::string name;
152                 unsigned id = 0;
153                 unsigned size = 0;
154                 std::vector<StructMember> members;
155         };
156
157         struct Variable
158         {
159                 std::string name;
160                 unsigned id = 0;
161                 DataType type = VOID;
162                 const Structure *struct_type = 0;
163                 StorageClass storage = static_cast<StorageClass>(-1);
164                 unsigned array_size = 0;
165                 int location = -1;
166                 unsigned descriptor_set = 0;
167                 int binding = -1;
168                 BuiltinSemantic builtin = NOT_BUILTIN;
169
170                 bool operator==(const Variable &) const;
171         };
172
173         struct Constant
174         {
175                 std::string name;
176                 unsigned id = 0;
177                 int constant_id = -1;
178                 DataType type = VOID;
179                 union
180                 {
181                         int i_value = 0;
182                         float f_value;
183                 };
184         };
185
186         struct InstructionBlock
187         {
188                 unsigned id = 0;
189                 bool negate_condition = false;
190                 const Constant *condition = 0;
191                 std::vector<const Variable *> accessed_variables;
192                 std::vector<const InstructionBlock *> successors;
193         };
194
195 private:
196         struct TypeInfo
197         {
198                 DataType type = VOID;
199                 const Structure *struct_type = 0;
200                 unsigned array_size = 0;
201                 unsigned array_stride = 0;
202                 StorageClass storage = static_cast<StorageClass>(-1);
203         };
204
205         struct Reflection
206         {
207                 typedef std::vector<std::uint32_t>::const_iterator CodeIterator;
208
209                 std::map<unsigned, std::string> names;
210                 std::map<unsigned, Constant> constants;
211                 std::map<unsigned, TypeInfo> types;
212                 std::map<unsigned, EntryPoint> entry_points;
213                 std::map<unsigned, Structure> structs;
214                 std::map<unsigned, Variable> variables;
215                 std::map<unsigned, InstructionBlock> blocks;
216                 std::map<unsigned, unsigned> access_chain_bases;
217                 Constant true_condition;
218                 InstructionBlock *current_block = 0;
219
220                 static std::uint32_t get_opcode(std::uint32_t);
221                 static CodeIterator get_op_end(const CodeIterator &);
222                 static std::string read_string(CodeIterator &, const CodeIterator &);
223
224                 void reflect_code(const std::vector<std::uint32_t> &);
225                 void reflect_name(CodeIterator);
226                 void reflect_member_name(CodeIterator);
227                 void reflect_entry_point(CodeIterator);
228                 void reflect_void_type(CodeIterator);
229                 void reflect_bool_type(CodeIterator);
230                 void reflect_int_type(CodeIterator);
231                 void reflect_float_type(CodeIterator);
232                 void reflect_vector_type(CodeIterator);
233                 void reflect_matrix_type(CodeIterator);
234                 void reflect_image_type(CodeIterator);
235                 void reflect_sampled_image_type(CodeIterator);
236                 void reflect_array_type(CodeIterator);
237                 void reflect_struct_type(CodeIterator);
238                 void reflect_pointer_type(CodeIterator);
239                 void reflect_constant(CodeIterator);
240                 void reflect_variable(CodeIterator);
241                 void reflect_access(CodeIterator);
242                 void reflect_access_chain(CodeIterator);
243                 void reflect_decorate(CodeIterator);
244                 void reflect_member_decorate(CodeIterator);
245                 void reflect_label(CodeIterator);
246                 void reflect_branch(CodeIterator);
247                 void reflect_branch_conditional(CodeIterator);
248         };
249
250         std::vector<std::uint32_t> code;
251         std::vector<EntryPoint> entry_points;
252         std::vector<Structure> structs;
253         std::vector<Variable> variables;
254         std::vector<Constant> spec_constants;
255         std::vector<InstructionBlock> blocks;
256         bool specializable = false;
257
258 public:
259         virtual Format get_format() const { return SPIR_V; }
260
261         /** Loads a SPIR-V binary from a file or other I/O object. */
262         void load_code(IO::Base &);
263 private:
264         virtual void compile(SL::Compiler &);
265         void reflect();
266
267 public:
268         const std::vector<std::uint32_t> &get_code() const { return code; }
269         const std::vector<EntryPoint> &get_entry_points() const { return entry_points; }
270         const std::vector<Variable> &get_variables() const { return variables; }
271         const std::vector<Constant> &get_spec_constants() const { return spec_constants; }
272         const std::vector<InstructionBlock> &get_blocks() const { return blocks; }
273         bool is_specializable() const { return specializable; }
274
275         /** Creates a new module which is a specialized version of this one. */
276         SpirVModule *specialize(const std::map<std::string, int> &) const;
277
278 private:
279         std::vector<const InstructionBlock *> collect_visited_blocks(const std::map<unsigned, int> &) const;
280         void collect_visited_blocks(unsigned, std::vector<std::uint8_t> &) const;
281 };
282
283 } // namespace GL
284 } // namespace Msp
285
286 #endif