]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/spirvwriter.cpp
Redesign framebuffer attachment management
[libs/gl.git] / source / glsl / spirvwriter.cpp
1 #include "glsl_error.h"
2 #include "spirvwriter.h"
3
4 using namespace std;
5
6 namespace Msp {
7 namespace GL {
8 namespace SL {
9
10 SpirVWriter::SpirVWriter(SpirVContent &c):
11         content(c),
12         op_target(0),
13         op_head_pos(0),
14         current_block_id(0)
15 { }
16
17 void SpirVWriter::append(vector<Word> &target, const vector<Word> &source)
18 {
19         target.insert(target.end(), source.begin(), source.end());
20 }
21
22 void SpirVWriter::write(Word word)
23 {
24         if(!op_target)
25                 throw logic_error("write without begin_op");
26         op_target->push_back(word);
27 }
28
29 void SpirVWriter::write_float(float value)
30 {
31         union
32         {
33                 float fv;
34                 Word word;
35         };
36         fv = value;
37         write(word);
38 }
39
40 void SpirVWriter::write_string(const string &str)
41 {
42         for(unsigned i=0; i<=str.size(); i+=4)
43         {
44                 Word word = 0;
45                 for(unsigned j=0; (j<4 && i+j<str.size()); ++j)
46                         word |= static_cast<unsigned char>(str[i+j])<<(j*8);
47                 write(word);
48         }
49 }
50
51 void SpirVWriter::begin_op(vector<Word> &target, Opcode opcode, unsigned size)
52 {
53         if(op_target)
54                 throw logic_error("begin_op without end_op");
55         if(&target==&content.function_body && !current_block_id)
56                 throw logic_error("no open block in function");
57
58         op_head_pos = target.size();
59         op_target = &target;
60         write(opcode | (size<<16));
61
62         if(opcode==OP_BRANCH || opcode==OP_BRANCH_CONDITIONAL || opcode==OP_KILL ||
63                 opcode==OP_RETURN || opcode==OP_RETURN_VALUE || opcode==OP_UNREACHABLE)
64                 current_block_id = 0;
65 }
66
67 void SpirVWriter::end_op(Opcode opcode)
68 {
69         if(!op_target)
70                 throw logic_error("end_op without begin_op");
71         Word &op_head = (*op_target)[op_head_pos];
72         if(opcode!=(op_head&0xFFFF))
73                 throw logic_error("opcode mismatch");
74
75         unsigned words = op_target->size()-op_head_pos;
76         unsigned op_size = op_head>>16;
77         if(op_size)
78         {
79                 if(words!=op_size)
80                         throw logic_error("incorred number of words written");
81         }
82         else
83                 op_head |= (words<<16);
84
85         op_target = 0;
86         op_head_pos = 0;
87 }
88
89 void SpirVWriter::write_op(vector<Word> &target, Opcode opcode)
90 {
91         begin_op(target, opcode, 1);
92         end_op(opcode);
93 }
94
95 void SpirVWriter::write_op(vector<Word> &target, Opcode opcode, Word arg0)
96 {
97         begin_op(target, opcode, 2);
98         write(arg0);
99         end_op(opcode);
100 }
101
102 void SpirVWriter::write_op(vector<Word> &target, Opcode opcode, Word arg0, Word arg1)
103 {
104         begin_op(target, opcode, 3);
105         write(arg0);
106         write(arg1);
107         end_op(opcode);
108 }
109
110 void SpirVWriter::write_op(vector<Word> &target, Opcode opcode, Word arg0, Word arg1, Word arg2)
111 {
112         begin_op(target, opcode, 4);
113         write(arg0);
114         write(arg1);
115         write(arg2);
116         end_op(opcode);
117 }
118
119 void SpirVWriter::write_op_name(Id id, const string &name)
120 {
121         begin_op(content.names, OP_NAME);
122         write(id);
123         write_string(name);
124         end_op(OP_NAME);
125 }
126
127 void SpirVWriter::write_op_member_name(Id id, unsigned index, const string &name)
128 {
129         begin_op(content.names, OP_MEMBER_NAME);
130         write(id);
131         write(index);
132         write_string(name);
133         end_op(OP_MEMBER_NAME);
134 }
135
136 void SpirVWriter::write_op_decorate(Id id, Decoration decoration)
137 {
138         write_op(content.decorations, OP_DECORATE, id, decoration);
139 }
140
141 void SpirVWriter::write_op_decorate(Id id, Decoration decoration, Word value)
142 {
143         write_op(content.decorations, OP_DECORATE, id, decoration, value);
144 }
145
146 void SpirVWriter::write_op_member_decorate(Id id, unsigned index, Decoration decoration)
147 {
148         write_op(content.decorations, OP_MEMBER_DECORATE, id, index, decoration);
149 }
150
151 void SpirVWriter::write_op_member_decorate(Id id, unsigned index, Decoration decoration, Word value)
152 {
153         begin_op(content.decorations, OP_MEMBER_DECORATE, 5);
154         write(id);
155         write(index);
156         write(decoration);
157         write(value);
158         end_op(OP_MEMBER_DECORATE);
159 }
160
161 void SpirVWriter::write_op_label(Id label_id)
162 {
163         if(current_block_id)
164                 write_op(content.function_body, OP_BRANCH, label_id);
165         current_block_id = label_id;
166         write_op(content.function_body, OP_LABEL, label_id);
167 }
168
169 void SpirVWriter::begin_function_body(Id first_block_id)
170 {
171         if(!content.function_body.empty() || current_block_id)
172                 throw internal_error("begin_function without end_function");
173
174         current_block_id = first_block_id;
175         write_op(content.functions, OP_LABEL, first_block_id);
176 }
177
178 void SpirVWriter::end_function_body()
179 {
180         if(content.function_body.empty())
181                 throw internal_error("end_function without begin_function");
182         if(current_block_id)
183                 throw internal_error("end_function with open block");
184
185         append(content.functions, content.locals);
186         append(content.functions, content.function_body);
187         write_op(content.functions, OP_FUNCTION_END);
188
189         content.locals.clear();
190         content.function_body.clear();
191 }
192
193 void SpirVWriter::finalize(unsigned generator, Id id_bound)
194 {
195         content.code.push_back(SPIRV_MAGIC);
196         content.code.push_back(0x00010500);
197         content.code.push_back(generator<<16);
198         content.code.push_back(id_bound);
199         content.code.push_back(0);  // Reserved
200         append(content.code, content.capabilities);
201         append(content.code, content.extensions);
202         write_op(content.code, OP_MEMORY_MODEL, 0, 1);  // Logical, GLSL450
203         append(content.code, content.entry_points);
204         append(content.code, content.exec_modes);
205         append(content.code, content.names);
206         append(content.code, content.decorations);
207         append(content.code, content.globals);
208         append(content.code, content.functions);
209 }
210
211 } // namespace SL
212 } // namespace GL
213 } // namespace Msp