Symphony Of Empires
glsl_trans.cpp
Go to the documentation of this file.
1 // Eng3D - General purpouse game engine
2 // Copyright (C) 2021, Eng3D contributors
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <https://www.gnu.org/licenses/>.
16 //
17 // ----------------------------------------------------------------------------
18 // Name:
19 // glsl_trans.cpp
20 //
21 // Abstract:
22 // Does some important stuff.
23 // ----------------------------------------------------------------------------
24 
25 #include "eng3d/glsl_trans.hpp"
26 #include "eng3d/log.hpp"
27 
28 //
29 // GLSL Context
30 //
31 std::string Eng3D::GLSL::Context::get_identifier(std::string::iterator& it) {
32  const auto start_it = it;
33 
34  // Alphanumerics, _ and dots are allowed as identifiers
35  while(it != buffer.end() && (isalnum(*it) || *it == '_' || *it == '.'))
36  it++;
37 
38  std::string str = buffer.substr(std::distance(buffer.begin(), start_it), std::distance(start_it, it));
39  return str;
40 }
41 
42 std::string Eng3D::GLSL::Context::get_literal(std::string::iterator& it) {
43  const auto start_it = it;
44  // Literal
45  while(it != buffer.end() && (isdigit(*it) || *it == '.'))
46  it++;
47 
48  // Skip 'type' specifier
49  while(it != buffer.end() && isalpha(*it))
50  it++;
51 
52  std::string str = buffer.substr(std::distance(buffer.begin(), start_it), std::distance(start_it, it));
53  return str;
54 }
55 
57  // Output the final stuff
58  for(auto it = buffer.begin(); it != buffer.end(); ) {
59  while(it != buffer.end() && isspace(*it) && (*it == '\r'))
60  it++;
61 
62  if(it == buffer.end()) break;
63 
64  if(*it == '\n') {
66  it++;
67  } else if((*(it + 0) == '/' && *(it + 1) == '/')) {
68  it += 2;
69  // Single-line comments
70  while(it != buffer.end() && (*it != '\n'))
71  it++;
72  } else if((*(it + 0) == '/' && *(it + 1) == '*')) {
73  it += 2;
74  // Multiline comments
75  while((it + 1) != buffer.end()) {
76  if(*(it + 0) == '*' && *(it + 1) == '/') {
77  it += 2;
78  break;
79  } else if(*it == '\n') {
81  }
82  it++;
83  }
84  } else if(*it == '#') {
85  it++;
86  auto start_it = it;
87  while(it != buffer.end() && (*it != '\n'))
88  it++;
89 
91  tok.data = buffer.substr(std::distance(buffer.begin(), start_it), std::distance(start_it, it));
92  tokens.push_back(tok);
93  } else if(*it == ',') {
95  it++;
96  } else if(*it == ';') {
98  it++;
99  } else if(*it == '(') {
101  it++;
102  } else if(*it == ')') {
104  it++;
105  } else if(*it == '[') {
107  it++;
108  } else if(*it == ']') {
110  it++;
111  } else if(*it == '{') {
113  it++;
114  } else if(*it == '}') {
116  it++;
117  } else if(*it == '+') {
119  it++;
120  } else if(*it == '-') {
122  it++;
123  } else if(*it == '*') {
125  it++;
126  } else if(*it == '/') {
128  it++;
129  } else if(*it == '%') {
131  it++;
132  } else if(*it == '^') {
134  it++;
135  } else if(*it == '<') {
136  it++;
137  if(it != buffer.end() && *it == '=') {
139  it++;
140  } else {
142  }
143  } else if(*it == '>') {
144  it++;
145  if(it != buffer.end() && *it == '=') {
147  it++;
148  } else {
150  }
151  } else if(*it == '|') {
152  it++;
153  if(it != buffer.end() && *it == '|') {
155  it++;
156  } else {
158  }
159  } else if(*it == '&') {
160  it++;
161  if(it != buffer.end() && *it == '&') {
163  it++;
164  } else {
166  }
167  } else if(*it == '=') {
168  it++;
169  if(it != buffer.end() && *it == '=') {
171  it++;
172  } else {
174  }
175  } else if(*it == '?') {
177  it++;
178  } else if(*it == ':') {
180  it++;
181  } else if(*it == '.') {
183  it++;
184  } else if(*it == '!' && (it + 1) != buffer.end() && *(it + 1) == '=') {
186  it += 2;
187  } else {
188  if(isdigit(*it) || *it == '.') {
190  tok.data = get_literal(it);
191  tokens.push_back(tok);
192  } else if(isalnum(*it) || *it == '_') {
194  tok.data = get_identifier(it);
195  tokens.push_back(tok);
196  } else {
197  it++;
198  }
199  }
200  }
201 }
202 
205  // Register the primitive types
206  this->types = {
218  };
219 
221 
222  fn = Eng3D::GLSL::Function();
223  fn.name = "vec2";
224  fn.ret_type = "vec2";
225  fn.args.emplace_back("float", "x");
226  fn.args.emplace_back("float", "y");
227  funcs.push_back(fn);
228 
229  fn = Eng3D::GLSL::Function();
230  fn.name = "vec3";
231  fn.ret_type = "vec3";
232  fn.args.emplace_back("float", "x");
233  fn.args.emplace_back("float", "y");
234  fn.args.emplace_back("float", "z");
235  funcs.push_back(fn);
236 
237  fn = Eng3D::GLSL::Function();
238  fn.name = "vec4";
239  fn.ret_type = "vec4";
240  fn.args.emplace_back("float", "x");
241  fn.args.emplace_back("float", "y");
242  fn.args.emplace_back("float", "z");
243  fn.args.emplace_back("float", "w");
244  funcs.push_back(fn);
245 
246  // Register all the overloads for this function
247  std::vector<std::string> vec_types = { "vec2", "vec3", "vec4", "sampler2D" };
248  std::vector<std::string> vec_and_sample_types = { "vec2", "vec3", "vec4", "sampler2D" };
249 
250  for(const auto& it1 : vec_and_sample_types) {
251  for(const auto& it2 : vec_and_sample_types) {
252  fn = Eng3D::GLSL::Function();
253  fn.name = "mix";
254  fn.ret_type = "vec4";
255  fn.args.emplace_back(it1, "x");
256  fn.args.emplace_back(it2, "y");
257  fn.args.emplace_back("float", "weight");
258  funcs.push_back(fn);
259  }
260  }
261 
262  fn = Eng3D::GLSL::Function();
263  fn.name = "clamp";
264  for(const auto& it1 : vec_types) {
265  fn.ret_type = it1;
266  fn.args.emplace_back(it1, "num");
267  fn.args.emplace_back(it1, "min");
268  fn.args.emplace_back(it1, "max");
269  }
270  funcs.push_back(fn);
271 
272  fn = Eng3D::GLSL::Function();
273  fn.name = "min";
274  for(const auto& it1 : vec_types) {
275  fn.ret_type = it1;
276  fn.args.emplace_back(it1, "x");
277  fn.args.emplace_back(it1, "y");
278  }
279  funcs.push_back(fn);
280 
281  fn = Eng3D::GLSL::Function();
282  fn.name = "max";
283  for(const auto& it1 : vec_types) {
284  fn.ret_type = it1;
285  fn.args.emplace_back(it1, "x");
286  fn.args.emplace_back(it1, "y");
287  }
288  funcs.push_back(fn);
289 
290  for(const auto& tok : tokens) {
291  if(tok.type == Eng3D::GLSL::Token::Type::ASSIGN) {
292 
293  }
294  }
295 }
296 
298  auto it = tokens.begin();
299  std::string end_buffer;
300  int current_line = 1;
301 
302  while(it != tokens.end() && it->type == Eng3D::GLSL::Token::Type::NEWLINE)
303  it++;
304 
305  // Go after the first instance of a preprocessor macro
306  if(it->type == Eng3D::GLSL::Token::Type::MACRO) {
307  end_buffer += "#" + it->data + "\r\n";
308  line_numbers.push_back(current_line++);
309  it += 2; // Skip the NEWLINE also
310  for(const auto& define : defines) {
311  end_buffer += "#define " + define.name + " " + define.value + "\r\n";
312  line_numbers.push_back(current_line);
313  }
314  }
315 
316  bool had_newline = false;
317  for(; it != tokens.end(); it++) {
318  if(it->type != Eng3D::GLSL::Token::Type::NEWLINE)
319  had_newline = false;
320 
321  switch(it->type) {
323  end_buffer += "#" + it->data;
324  break;
326  line_numbers.push_back(current_line++);
327  if(!had_newline)
328  end_buffer += "\n";
329  had_newline = true;
330  break;
332  end_buffer += ";";
333  break;
335  end_buffer += ",";
336  break;
338  end_buffer += "(";
339  break;
341  end_buffer += ")";
342  break;
344  end_buffer += "[";
345  break;
347  end_buffer += "]";
348  break;
350  end_buffer += "{";
351  break;
353  end_buffer += "}";
354  break;
356  end_buffer += "+";
357  break;
359  end_buffer += "-";
360  break;
362  end_buffer += "*";
363  break;
365  end_buffer += "/";
366  break;
368  end_buffer += "%";
369  break;
371  end_buffer += "^";
372  break;
374  end_buffer += "&&";
375  break;
377  end_buffer += "&";
378  break;
380  end_buffer += "||";
381  break;
383  end_buffer += "|";
384  break;
386  end_buffer += "<";
387  break;
389  end_buffer += "<=";
390  break;
392  end_buffer += ">";
393  break;
395  end_buffer += ">=";
396  break;
398  end_buffer += "?";
399  break;
401  end_buffer += ":";
402  break;
404  end_buffer += ".";
405  break;
407  end_buffer += it->data;
408  break;
410  if(it->data == "layout")
411  end_buffer += it->data + " ";
412  else if(it->data == "provided")
413  end_buffer += "uniform ";
414  else if(it->data == "in")
415  end_buffer += "in ";
416  else if(it->data == "out")
417  end_buffer += "out ";
418  else
419  end_buffer += it->data + " ";
420  break;
422  end_buffer += "=";
423  break;
425  end_buffer += "==";
426  break;
428  end_buffer += "!=";
429  break;
430  default:
431  break;
432  }
433  }
434 
435  Eng3D::Log::debug("glsl_trans", end_buffer);
436  return end_buffer;
437 }
void parser()
Parses the current context's tokens and optimizes them.
Definition: glsl_trans.cpp:204
std::string get_literal(std::string::iterator &it)
Definition: glsl_trans.cpp:42
std::string to_text()
Definition: glsl_trans.cpp:297
std::string get_identifier(std::string::iterator &it)
Definition: glsl_trans.cpp:31
std::vector< std::pair< std::string, std::string > > args
Definition: glsl_trans.hpp:98
std::string ret_type
Definition: glsl_trans.hpp:99
std::string data
Definition: glsl_trans.hpp:57
void debug(const std::string_view category, const std::string_view msg)
Definition: log.cpp:58