145 struct unknown_uniform_storage : std::logic_error { unknown_uniform_storage() :
std::logic_error{
"neogfx::unknown_uniform_storage" } {} };
146 struct unknown_uniform_location : std::logic_error { unknown_uniform_location() :
std::logic_error{
"neogfx::unknown_uniform_location" } {} };
147 struct shader_variable_not_linked : std::logic_error { shader_variable_not_linked() :
std::logic_error{
"neogfx::shader_variable_not_linked" } {} };
148 struct shader_variable_not_found : std::logic_error { shader_variable_not_found() :
std::logic_error{
"neogfx::shader_variable_not_found" } {} };
149 struct invalid_shader_variable_type : std::logic_error { invalid_shader_variable_type() :
std::logic_error{
"neogfx::invalid_shader_variable_type" } {} };
150 struct unsupported_shader_language : std::logic_error { unsupported_shader_language() :
std::logic_error{
"neogfx::unsupported_shader_language" } {} };
155 template <shader_data_type HandleType>
159 typedef shader_handle<HandleType> self_type;
160 typedef self_type abstract_type;
161 bool operator==(
const self_type& aRhs)
const {
return handle == aRhs.handle; }
164 typedef shader_handle<shader_data_type::Sampler2D> sampler2D;
165 typedef shader_handle<shader_data_type::Sampler2DMS> sampler2DMS;
166 typedef shader_handle<shader_data_type::Sampler2DRect> sampler2DRect;
168 typedef neolib::plugin_variant<shader_data_type, bool, float, double, int32_t, uint32_t, vec2f, vec2, vec2i32, vec2u32, vec3f, vec3, vec3i32, vec3u32, vec4f, vec4, vec4i32, vec4u32, mat4f, mat4, shader_float_array, shader_double_array, sampler2D, sampler2DMS, sampler2DRect> shader_value_type;
170 typedef uint32_t shader_variable_location;
171 typedef void* shader_uniform_storage;
172 typedef int32_t shader_uniform_location;
175 constexpr shader_uniform_id no_uniform = shader_uniform_id{};
177 class i_shader_uniform
180 typedef i_shader_uniform abstract_type;
182 virtual shader_uniform_id
id()
const = 0;
183 virtual const i_string& name()
const = 0;
184 virtual bool shared()
const = 0;
185 virtual bool singular()
const = 0;
186 virtual bool has_storage()
const = 0;
187 virtual shader_uniform_storage storage()
const = 0;
188 virtual void set_storage(shader_uniform_storage aStorage) = 0;
189 virtual void clear_storage() = 0;
190 virtual bool has_location()
const = 0;
191 virtual shader_uniform_location location()
const = 0;
192 virtual void set_location(shader_uniform_location aLocation) = 0;
193 virtual void clear_location() = 0;
194 virtual const abstract_t<shader_value_type>& value()
const = 0;
195 virtual abstract_t<shader_value_type>& mutable_value() = 0;
196 virtual void set_value(
const abstract_t<shader_value_type>& aValue) = 0;
197 virtual bool is_dirty()
const = 0;
198 virtual void clean()
const = 0;
199 virtual bool different_type_to(
const abstract_t<shader_value_type>& aValue)
const = 0;
201 template <
typename T>
202 void set_value(
const T& aValue)
204 if constexpr (std::is_integral_v<T>)
206 if constexpr (std::is_same_v<T, bool>)
207 set_value(
to_abstract(shader_value_type{ aValue }));
208 else if constexpr (std::is_same_v<T, int32_t> || std::is_same_v<T, uint32_t>)
209 set_value(
to_abstract(shader_value_type{ aValue }));
210 else if constexpr (std::is_signed_v<T>)
211 set_value(
to_abstract(shader_value_type{
static_cast<int32_t
>(aValue) }));
212 else if constexpr (std::is_unsigned_v<T>)
213 set_value(
to_abstract(shader_value_type{
static_cast<uint32_t
>(aValue) }));
215 set_value(
to_abstract(shader_value_type{
static_cast<int32_t
>(aValue) }));
217 else if constexpr (std::is_enum_v<T>)
218 set_value(
to_abstract(shader_value_type{
static_cast<int32_t
>(aValue) }));
220 set_value(
to_abstract(shader_value_type{ aValue }));
224 class shader_uniform :
public i_shader_uniform
226 typedef i_shader_uniform base_type;
228 typedef base_type abstract_type;
230 typedef std::variant<std::monostate, shader_uniform_storage, shader_uniform_location> placement;
232 template <
typename T>
233 shader_uniform(shader_uniform_id aId,
const string& aName,
bool aShared,
const T& aValue) :
241 shader_uniform(
const shader_uniform& aOther) :
243 iName{ aOther.iName },
244 iShared{ aOther.iShared },
245 iValue{ aOther.iValue },
249 shader_uniform(shader_uniform&& aOther) noexcept :
250 iId{ std::move(aOther.iId) },
251 iName{ std::move(aOther.iName) },
252 iShared{ std::move(aOther.iShared) },
253 iValue{ std::move(aOther.iValue) },
257 shader_uniform(
const i_shader_uniform& aOther) :
259 iName{ aOther.name() },
260 iShared{ aOther.shared()},
261 iValue{ aOther.value() },
266 shader_uniform& operator=(
const shader_uniform& aOther)
270 this->~shader_uniform();
271 new (
this) shader_uniform{ aOther };
274 shader_uniform& operator=(shader_uniform&& aOther)
noexcept
278 iId = std::move(aOther.iId);
279 iName = std::move(aOther.iName);
280 iShared = std::move(aOther.iShared);
281 iValue = std::move(aOther.iValue);
286 shader_uniform_id
id() const final
290 const i_string& name() const final
294 bool shared() const final
298 bool singular() const final
300 if (!value().empty())
302 switch (value().which())
304 case shader_data_type::Sampler2D:
305 case shader_data_type::Sampler2DMS:
306 case shader_data_type::Sampler2DRect:
312 bool has_storage() const final
314 return std::holds_alternative<shader_uniform_storage>(iPlacement);
316 shader_uniform_storage storage() const final
319 return std::get<shader_uniform_storage>(iPlacement);
320 throw unknown_uniform_storage();
322 void set_storage(shader_uniform_storage aStorage)
final
324 iPlacement = aStorage;
326 void clear_storage() final
329 iPlacement = std::monostate{};
331 bool has_location() const final
333 return std::holds_alternative<shader_uniform_location>(iPlacement);
335 shader_uniform_location location() const final
338 return std::get<shader_uniform_location>(iPlacement);
339 throw unknown_uniform_location();
341 void set_location(shader_uniform_location aLocation)
final
343 iPlacement = aLocation;
345 void clear_location() final
348 iPlacement = std::monostate{};
350 const abstract_t<shader_value_type>& value() const final
354 abstract_t<shader_value_type>& mutable_value() final
359 void set_value(
const abstract_t<shader_value_type>& aValue)
final
361 if (iValue != aValue)
367 bool is_dirty() const final
371 void clean() const final
375 bool different_type_to(
const abstract_t<shader_value_type>& aValue)
const
377 if (value().which() != aValue.which())
379 switch (value().which())
381 case shader_data_type::FloatArray:
382 return value().get<abstract_t<shader_float_array>>().
size() !=
383 aValue.get<abstract_t<shader_float_array>>().
size();
384 case shader_data_type::DoubleArray:
385 return value().get<abstract_t<shader_double_array>>().
size() !=
386 aValue.get<abstract_t<shader_double_array>>().
size();
392 shader_uniform_id iId;
395 placement iPlacement;
396 shader_value_type iValue;
400 class i_shader_variable
403 typedef i_shader_variable abstract_type;
405 virtual const i_string& name()
const = 0;
406 virtual shader_variable_location location()
const = 0;
407 virtual const i_enum_t<shader_variable_qualifier>& qualifier()
const = 0;
408 virtual const i_enum_t<shader_data_type>& type()
const = 0;
409 virtual bool has_link()
const = 0;
410 virtual const i_shader_variable& link()
const = 0;
411 virtual void link(
const i_shader_variable& aOther) = 0;
412 virtual void reset_link() = 0;
415 class shader_variable :
public i_shader_variable
417 typedef i_shader_variable base_type;
419 typedef base_type abstract_type;
423 shader_variable_location aLocation,
424 shader_variable_qualifier aQualifier,
425 shader_data_type aType) :
427 iLocation{ aLocation },
428 iQualifier{ aQualifier },
433 shader_variable(
const i_shader_variable& aOther) :
434 iName{ aOther.name() },
435 iLocation{ aOther.location() },
436 iQualifier{ aOther.qualifier() },
437 iType{ aOther.type() },
440 if (aOther.has_link())
444 const i_string& name() const final
448 shader_variable_location location() const final
452 const i_enum_t<shader_variable_qualifier>& qualifier() const final
456 const i_enum_t<shader_data_type>& type() const final
460 bool has_link() const final
462 return iLink !=
nullptr;
464 const i_shader_variable& link() const final
468 throw shader_variable_not_linked();
470 void link(
const i_shader_variable& aOther)
final
474 void reset_link() final
479 bool operator<(
const shader_variable& aRhs)
const
481 return location() < aRhs.location();
485 shader_variable_location iLocation;
486 enum_t<shader_variable_qualifier> iQualifier;
487 enum_t<shader_data_type> iType;
488 const i_shader_variable* iLink;
491 class i_rendering_context;
492 class i_shader_program;
494 class i_shader :
public i_reference_counted
497 typedef i_shader abstract_type;
499 typedef abstract_t<shader_value_type> value_type;
503 virtual ~i_shader() =
default;
506 virtual const i_string& name()
const = 0;
507 virtual bool supports(vertex_buffer_type aBufferType)
const = 0;
508 virtual void* handle(
const i_shader_program& aProgram)
const = 0;
509 virtual bool enabled()
const = 0;
510 virtual bool disabled()
const = 0;
511 virtual void enable() = 0;
512 virtual void disable() = 0;
513 virtual bool dirty()
const = 0;
514 virtual void set_dirty() = 0;
515 virtual void set_clean() = 0;
516 virtual bool uniforms_changed()
const = 0;
518 virtual const uniform_list& uniforms()
const = 0;
519 virtual bool has_shared_uniforms()
const = 0;
520 virtual void clear_uniform(shader_uniform_id aUniform) = 0;
521 virtual shader_uniform_id create_uniform(
const i_string& aName,
bool aShared =
false) = 0;
522 virtual shader_uniform_id find_uniform(
const i_string& aName)
const = 0;
523 virtual void set_uniform(shader_uniform_id aUniform, value_type
const& aValue) = 0;
524 virtual void clear_uniform_storage(shader_uniform_id aUniform) = 0;
525 virtual void update_uniform_storage(shader_uniform_id aUniform, shader_uniform_storage aStorage) = 0;
526 virtual void clear_uniform_location(shader_uniform_id aUniform) = 0;
527 virtual void update_uniform_location(shader_uniform_id aUniform, shader_uniform_location aLocation) = 0;
528 virtual const variable_list& in_variables()
const = 0;
529 virtual const variable_list& out_variables()
const = 0;
530 virtual void clear_variable(
const i_string& aName) = 0;
531 virtual i_shader_variable& add_variable(
const i_shader_variable& aVariable) = 0;
533 virtual void prepare_uniforms(
const i_rendering_context& aContext, i_shader_program& aProgram) = 0;
534 virtual void generate_code(
const i_shader_program& aProgram, shader_language aLanguage, i_string& aOutput)
const = 0;
535 virtual void generate_invoke(
const i_shader_program& aProgram, shader_language aLanguage, i_string& aInvokes)
const = 0;
538 void set_uniform(
const i_string& aName, value_type
const& aValue)
540 auto existing = find_uniform(aName);
541 if (existing == no_uniform)
542 existing = create_uniform(aName);
543 set_uniform(existing, aValue);
545 template <
typename T>
546 void set_uniform(
const i_string& aName,
const T& aValue)
548 if constexpr (!std::is_enum_v<T>)
549 set_uniform(aName,
to_abstract(shader_value_type{ aValue }));
551 set_uniform(aName,
to_abstract(shader_value_type{
static_cast<int>(aValue) }));
553 template <std::
size_t ArraySize>
554 void set_uniform(
const i_string& aName,
const float(&aArray)[ArraySize])
556 set_uniform(aName, shader_float_array{ &aArray[0], &aArray[0] + ArraySize });
558 template <std::
size_t ArraySize>
559 void set_uniform(
const i_string& aName,
const double(&aArray)[ArraySize])
561 set_uniform(aName, shader_double_array{ &aArray[0], &aArray[0] + ArraySize });
563 void set_uniform(
const i_string& aName,
const float* aArray, std::size_t aArraySize)
565 set_uniform(aName, shader_float_array{ aArray, aArray + aArraySize });
567 void set_uniform(
const i_string& aName,
const double* aArray, std::size_t aArraySize)
569 set_uniform(aName, shader_double_array{ aArray, aArray + aArraySize });
571 template <
typename T>
572 i_shader_variable& add_in_variable(
const i_string& aName, shader_variable_location aLocation,
bool aFlat =
false)
578 aFlat ? shader_variable_qualifier::In | shader_variable_qualifier::Flat : shader_variable_qualifier::In,
581 template <
typename T>
582 i_shader_variable& add_out_variable(
const i_string& aName, shader_variable_location aLocation,
bool aFlat =
false)
588 aFlat ? shader_variable_qualifier::Out | shader_variable_qualifier::Flat : shader_variable_qualifier::Out,
593 template <
typename Shader,
typename... Args>
#define end_declare_enum(enumName)
#define declare_enum_string_explicit(enumName, enumEnumerator, enumString)
#define declare_enum_string(enumName, enumEnumerator)
#define begin_declare_enum(enumName)
shader_variable_qualifier
constexpr style_aspect operator&(style_aspect aLhs, style_aspect aRhs)
bool operator<(const basic_rect< CoordinateType, CoordinateSystem > &left, const basic_rect< CoordinateType, CoordinateSystem > &right)
bool operator==(const basic_rect< CoordinateType, CoordinateSystem > &left, const basic_rect< CoordinateType, CoordinateSystem > &right)
constexpr style_aspect operator|(style_aspect aLhs, style_aspect aRhs)
basic_size< coordinate > size
const abstract_t< T > & to_abstract(const T &aArgument)
ref_ptr< ConcreteType > make_ref(Args &&... args)