Loading...
Searching...
No Matches
GppShaders.hpp
1#pragma once
2#include <Crousti/GppCoroutines.hpp>
3#include <avnd/concepts/all.hpp>
4#include <fmt/format.h>
5#include <string_view>
6
7namespace gpp::qrhi
8{
10{
11 template <typename T, int N>
12 using vec = T[N];
13
14 static constexpr std::string_view field_type(float) { return "float"; }
15 static constexpr std::string_view field_type(const float (&)[2]) { return "vec2"; }
16 static constexpr std::string_view field_type(const float (&)[3]) { return "vec3"; }
17 static constexpr std::string_view field_type(const float (&)[4]) { return "vec4"; }
18
19 static constexpr std::string_view field_type(float*) { return "float"; }
20 static constexpr std::string_view field_type(vec<float, 2>*) { return "vec2"; }
21 static constexpr std::string_view field_type(vec<float, 3>*) { return "vec3"; }
22 static constexpr std::string_view field_type(vec<float, 4>*) { return "vec4"; }
23
24 static constexpr std::string_view field_type(int) { return "int"; }
25 static constexpr std::string_view field_type(const int (&)[2]) { return "ivec2"; }
26 static constexpr std::string_view field_type(const int (&)[3]) { return "ivec3"; }
27 static constexpr std::string_view field_type(const int (&)[4]) { return "ivec4"; }
28
29 static constexpr std::string_view field_type(int*) { return "int"; }
30 static constexpr std::string_view field_type(vec<int, 2>*) { return "ivec2"; }
31 static constexpr std::string_view field_type(vec<int, 3>*) { return "ivec3"; }
32 static constexpr std::string_view field_type(vec<int, 4>*) { return "ivec4"; }
33
34 static constexpr std::string_view field_type(uint32_t) { return "uint"; }
35 static constexpr std::string_view field_type(const uint32_t (&)[2]) { return "uvec2"; }
36 static constexpr std::string_view field_type(const uint32_t (&)[3]) { return "uvec3"; }
37 static constexpr std::string_view field_type(const uint32_t (&)[4]) { return "uvec4"; }
38
39 static constexpr std::string_view field_type(uint32_t*) { return "uint"; }
40 static constexpr std::string_view field_type(vec<uint32_t, 2>*) { return "uvec2"; }
41 static constexpr std::string_view field_type(vec<uint32_t, 3>*) { return "uvec3"; }
42 static constexpr std::string_view field_type(vec<uint32_t, 4>*) { return "uvec4"; }
43
44 static constexpr std::string_view field_type(avnd::xy_value auto) { return "vec2"; }
45
46 static constexpr bool field_array(float) { return false; }
47 static constexpr bool field_array(const float (&)[2]) { return false; }
48 static constexpr bool field_array(const float (&)[3]) { return false; }
49 static constexpr bool field_array(const float (&)[4]) { return false; }
50
51 static constexpr bool field_array(float*) { return true; }
52 static constexpr bool field_array(vec<float, 2>*) { return true; }
53 static constexpr bool field_array(vec<float, 3>*) { return true; }
54 static constexpr bool field_array(vec<float, 4>*) { return true; }
55
56 static constexpr bool field_array(int) { return false; }
57 static constexpr bool field_array(const int (&)[2]) { return false; }
58 static constexpr bool field_array(const int (&)[3]) { return false; }
59 static constexpr bool field_array(const int (&)[4]) { return false; }
60
61 static constexpr bool field_array(int*) { return true; }
62 static constexpr bool field_array(vec<int, 2>*) { return true; }
63 static constexpr bool field_array(vec<int, 3>*) { return true; }
64 static constexpr bool field_array(vec<int, 4>*) { return true; }
65
66 static constexpr bool field_array(uint32_t) { return false; }
67 static constexpr bool field_array(const uint32_t (&)[2]) { return false; }
68 static constexpr bool field_array(const uint32_t (&)[3]) { return false; }
69 static constexpr bool field_array(const uint32_t (&)[4]) { return false; }
70
71 static constexpr bool field_array(uint32_t*) { return true; }
72 static constexpr bool field_array(vec<uint32_t, 2>*) { return true; }
73 static constexpr bool field_array(vec<uint32_t, 3>*) { return true; }
74 static constexpr bool field_array(vec<uint32_t, 4>*) { return true; }
75
76 static constexpr bool field_array(avnd::xy_value auto) { return false; }
77
78 template <typename T>
79 static constexpr std::string_view image_qualifier()
80 {
81 if constexpr(requires { T::readonly; })
82 return "readonly";
83 else if constexpr(requires { T::writeonly; })
84 return "writeonly";
85 else
86 static_assert(T::readonly || T::writeonly);
87 }
88
90 {
91 std::string& shader;
92
93 template <typename T>
94 void operator()(const T& field)
95 {
96 shader += fmt::format(
97 "layout(location = {}) in {} {};\n", T::location(), field_type(field.data),
98 T::name());
99 }
100 };
101
103 {
104 std::string& shader;
105
106 template <typename T>
107 void operator()(const T& field)
108 {
109 if constexpr(requires { field.location(); })
110 {
111 shader += fmt::format(
112 "layout(location = {}) out {} {};\n", T::location(), field_type(field.data),
113 T::name());
114 }
115 }
116 };
117
119 {
120 std::string& shader;
121
122 template <typename T>
123 void operator()(const T& field)
124 {
125 shader += fmt::format(
126 " {} {}{};\n", field_type(field.value), T::name(),
127 field_array(field.value) ? "[]" : "");
128 }
129 };
130
132 {
133 std::string& shader;
134
135 template <typename C>
136 void operator()(const C& field)
137 {
138 if constexpr(requires { C::sampler2D; })
139 {
140 shader += fmt::format(
141 "layout(binding = {}) uniform sampler2D {};\n\n", C::binding(), C::name());
142 }
143 else if constexpr(requires { C::image2D; })
144 {
145 shader += fmt::format(
146 "layout(binding = {}, {}) {} uniform image2D {};\n\n", C::binding(),
147 C::format(), image_qualifier<C>(), C::name());
148 }
149 else if constexpr(requires { C::ubo; })
150 {
151 shader += fmt::format(
152 "layout({}, binding = {}) uniform {}\n{{\n",
153 "std140" // TODO
154 ,
155 C::binding(), C::name());
156
157 boost::pfr::for_each_field(field, write_binding{shader});
158
159 shader += fmt::format("}};\n\n");
160 }
161 else if constexpr(requires { C::buffer; })
162 {
163 shader += fmt::format(
164 "layout({}, binding = {}) buffer {}\n{{\n",
165 "std140" // TODO
166 ,
167 C::binding(), C::name());
168
169 boost::pfr::for_each_field(field, write_binding{shader});
170
171 shader += fmt::format("}};\n\n");
172 }
173 }
174 };
175
176 template <typename T>
177 std::string vertex_shader(const T& lay)
178 {
179 using namespace gpp::qrhi;
180 std::string shader = "#version 450\n\n";
181
182 if constexpr(requires { lay.vertex_input; })
183 boost::pfr::for_each_field(lay.vertex_input, write_input{shader});
184 else if constexpr(requires { typename T::vertex_input; })
185 boost::pfr::for_each_field(typename T::vertex_input{}, write_input{shader});
186 else
187 boost::pfr::for_each_field(
188 DefaultPipeline::layout::vertex_input{}, write_input{shader});
189
190 if constexpr(requires { lay.vertex_output; })
191 boost::pfr::for_each_field(lay.vertex_output, write_output{shader});
192 else if constexpr(requires { typename T::vertex_output; })
193 boost::pfr::for_each_field(typename T::vertex_output{}, write_output{shader});
194
195 shader += "\n";
196
197 if constexpr(requires { lay.bindings; })
198 boost::pfr::for_each_field(lay.bindings, write_bindings{shader});
199 else if constexpr(requires { typename T::bindings; })
200 boost::pfr::for_each_field(typename T::bindings{}, write_bindings{shader});
201
202 return shader;
203 }
204
205 template <typename T>
206 std::string fragment_shader(const T& lay)
207 {
208 std::string shader = "#version 450\n\n";
209
210 if constexpr(requires { lay.fragment_input; })
211 boost::pfr::for_each_field(lay.fragment_input, write_input{shader});
212 else if constexpr(requires { typename T::fragment_input; })
213 boost::pfr::for_each_field(typename T::fragment_input{}, write_input{shader});
214
215 if constexpr(requires { lay.fragment_output; })
216 boost::pfr::for_each_field(lay.fragment_output, write_output{shader});
217 else if constexpr(requires { typename T::fragment_output; })
218 boost::pfr::for_each_field(typename T::fragment_output{}, write_output{shader});
219
220 shader += "\n";
221
222 if constexpr(requires { lay.bindings; })
223 boost::pfr::for_each_field(lay.bindings, write_bindings{shader});
224 else if constexpr(requires { typename T::bindings; })
225 boost::pfr::for_each_field(typename T::bindings{}, write_bindings{shader});
226
227 return shader;
228 }
229
230 template <typename T>
231 std::string compute_shader(const T& lay)
232 {
233 std::string fstr = "#version 450\n\n";
234
235 fstr += "layout(";
236 if constexpr(requires { T::local_size_x(); })
237 {
238 fstr += fmt::format("local_size_x = {}, ", T::local_size_x());
239 }
240 if constexpr(requires { T::local_size_y(); })
241 {
242 fstr += fmt::format("local_size_y = {}, ", T::local_size_y());
243 }
244 if constexpr(requires { T::local_size_z(); })
245 {
246 fstr += fmt::format("local_size_z = {}, ", T::local_size_z());
247 }
248
249 // Remove the last ", "
250 fstr.resize(fstr.size() - 2);
251 fstr += ") in;\n\n";
252
253 boost::pfr::for_each_field(lay.bindings, write_bindings{fstr});
254
255 return fstr;
256 }
257};
258}
Definition GppShaders.hpp:119
Definition GppShaders.hpp:132
Definition GppShaders.hpp:90
Definition GppShaders.hpp:103
Definition GppShaders.hpp:10