11 template <
typename T,
int N>
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"; }
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"; }
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"; }
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"; }
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"; }
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"; }
44 static constexpr std::string_view field_type(avnd::xy_value
auto) {
return "vec2"; }
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; }
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; }
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; }
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; }
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; }
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; }
76 static constexpr bool field_array(avnd::xy_value
auto) {
return false; }
79 static constexpr std::string_view image_qualifier()
81 if constexpr(
requires { T::readonly; })
83 else if constexpr(
requires { T::writeonly; })
86 static_assert(T::readonly || T::writeonly);
94 void operator()(
const T& field)
96 shader += fmt::format(
97 "layout(location = {}) in {} {};\n", T::location(), field_type(field.data),
106 template <
typename T>
107 void operator()(
const T& field)
109 if constexpr(
requires { field.location(); })
111 shader += fmt::format(
112 "layout(location = {}) out {} {};\n", T::location(), field_type(field.data),
122 template <
typename T>
123 void operator()(
const T& field)
125 shader += fmt::format(
126 " {} {}{};\n", field_type(field.value), T::name(),
127 field_array(field.value) ?
"[]" :
"");
135 template <
typename C>
136 void operator()(
const C& field)
138 if constexpr(
requires { C::sampler2D; })
140 shader += fmt::format(
141 "layout(binding = {}) uniform sampler2D {};\n\n", C::binding(), C::name());
143 else if constexpr(
requires { C::image2D; })
145 shader += fmt::format(
146 "layout(binding = {}, {}) {} uniform image2D {};\n\n", C::binding(),
147 C::format(), image_qualifier<C>(), C::name());
149 else if constexpr(
requires { C::ubo; })
151 shader += fmt::format(
152 "layout({}, binding = {}) uniform {}\n{{\n",
155 C::binding(), C::name());
159 shader += fmt::format(
"}};\n\n");
161 else if constexpr(
requires { C::buffer; })
163 shader += fmt::format(
164 "layout({}, binding = {}) buffer {}\n{{\n",
167 C::binding(), C::name());
171 shader += fmt::format(
"}};\n\n");
176 template <
typename T>
177 std::string vertex_shader(
const T& lay)
179 using namespace gpp::qrhi;
180 std::string shader =
"#version 450\n\n";
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});
187 boost::pfr::for_each_field(
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});
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});
205 template <
typename T>
206 std::string fragment_shader(
const T& lay)
208 std::string shader =
"#version 450\n\n";
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});
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});
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});
230 template <
typename T>
231 std::string compute_shader(
const T& lay)
233 std::string fstr =
"#version 450\n\n";
236 if constexpr(
requires { T::local_size_x(); })
238 fstr += fmt::format(
"local_size_x = {}, ", T::local_size_x());
240 if constexpr(
requires { T::local_size_y(); })
242 fstr += fmt::format(
"local_size_y = {}, ", T::local_size_y());
244 if constexpr(
requires { T::local_size_z(); })
246 fstr += fmt::format(
"local_size_z = {}, ", T::local_size_z());
250 fstr.resize(fstr.size() - 2);
253 boost::pfr::for_each_field(lay.bindings, write_bindings{fstr});