27#include "shader.glsl.hpp"
28#include "shader.glsl-gles.hpp"
32 #define cache_uniform( uniformName ) cached_uniform uniformName = { *this, #uniformName };
33 #define cache_shared_uniform( uniformName ) cached_uniform uniformName = { *this, #uniformName, true };
35 template <
typename Base>
41 using typename base_type::abstract_type;
51 iParent{ aParent }, iName{ aName }, iShared{ aShared }
59 auto existing = iParent.find_uniform(iName);
60 if (existing != no_uniform)
62 if (iId == std::nullopt)
63 iId = iParent.create_uniform(iName, iShared);
65 return iParent.uniforms()[*iId];
69 return const_cast<i_shader_uniform&
>(to_const(*this).uniform());
81 mutable cache<shader_uniform_id> iId;
89 iHasSharedUniforms{ false }
95 service<i_rendering_engine>().destroy_shader_object(*iHandle);
112 if (!aProgram.is_first_in_stage(*
this))
113 return aProgram.first_in_stage(
type()).handle(aProgram);
115 iHandle = service<i_rendering_engine>().create_shader_object(
type());
116 if (*iHandle ==
nullptr)
166 const i_shader::uniform_list&
uniforms() const final
168 return iUniforms.items();
172 return iHasSharedUniforms;
182 iUniforms.remove(aUniform);
189 iHasSharedUniforms = iHasSharedUniforms || aShared;
196 if (u.name() == aName)
200 using i_shader::set_uniform;
204 if (u.value().empty() != aValue.empty() || (!u.value().empty() && u.different_type_to(aValue)))
210 uniforms()[aUniform].clear_storage();
214 uniforms()[aUniform].set_storage(aStorage);
218 uniforms()[aUniform].clear_location();
222 uniforms()[aUniform].set_location(aLocation);
230 return iOutVariables;
235 if (v->name() == aName)
241 if (v->name() == aName)
247 i_shader_variable&
add_variable(
const i_shader_variable& aVariable)
final
250 iInVariables : iOutVariables);
251 auto existing = variableList.find(aVariable);
252 if (existing == variableList.end())
254 auto& v = *variableList.insert(aVariable);
258 if (existing->name() != aVariable.name())
260 *existing = aVariable;
273 switch (service<i_rendering_engine>().
renderer())
278 aOutput = glsl::Shader;
281 aOutput = glsl::gles::Shader;
286 throw unsupported_shader_language();
292 std::map<string, string> uniformDefinitions;
293 std::map<string, string> singularUniformDefinitions;
294 std::map<std::pair<shader_variable_qualifier, shader_variable_location>,
string> variableDefinitions;
295 for (
auto const& s : aProgram.
stage(
type())->shaders())
297 for (
auto const& u : s->uniforms())
299 if (s->disabled() && !u.shared())
301 string uniformDefinition;
302 switch (u.value().which())
305 uniformDefinition =
" float %I%["_s +
to_string(u.value().get<abstract_t<shader_float_array>>().size()) +
"];\n"_s;
308 uniformDefinition =
" double %I%["_s +
to_string(u.value().get<abstract_t<shader_double_array>>().size()) +
"];\n"_s;
312 uniformDefinition =
" %T% %I%;\n"_s;
314 uniformDefinition =
"uniform %T% %I%;\n"_s;
317 uniformDefinition.
replace_all(
"%T%"_s, enum_to_string(u.value().which()));
320 uniformDefinitions[u.name()] = uniformDefinition;
322 singularUniformDefinitions[u.name()] = uniformDefinition;
326 for (
auto const& v : s->in_variables())
328 string variableDefinition =
"layout (location = %L%) %I% in %T% %N%;\n"_s;
332 variableDefinition.
replace_all(
"%T%"_s, enum_to_string<shader_data_type>(v.type()));
335 variableDefinitions[std::make_pair(v.qualifier().value<
shader_variable_qualifier>(), v.location())] = variableDefinition;
337 for (
auto const& v : s->out_variables())
339 string variableDefinition =
"layout (location = %L%) %I% out %T% %N%;\n"_s;
343 variableDefinition.
replace_all(
"%T%"_s, enum_to_string<shader_data_type>(v.type()));
346 variableDefinitions[std::make_pair(v.qualifier().value<
shader_variable_qualifier>(), v.location())] = variableDefinition;
350 for (
auto const& udef : uniformDefinitions)
351 udefs += udef.second;
353 for (
auto const& sudef : singularUniformDefinitions)
354 sudefs += sudef.second;
356 for (
auto const& vdef : variableDefinitions)
357 vdefs += vdef.second;
359 aOutput.
replace_all(
"%UNIFORM_BLOCK_NAME%"_s, enum_to_string(
type()) +
"Uniforms");
361 aOutput.
replace_all(
"%SINGULAR_UNIFORMS%"_s, sudefs);
365 throw unsupported_shader_language();
370 aInvokes +=
" "_s +
name() +
"("_s;
378 aInvokes += (
"arg"_s + out.name());
380 aInvokes +=
");\n"_s;
389 return iOutVariables;
394 mutable cache<void*> iHandle;
398 bool iHasSharedUniforms;
virtual bool is_last_in_stage(const i_shader &aShader) const =0
virtual bool is_first_in_stage(const i_shader &aShader) const =0
virtual const i_stage_t & stage(shader_type aStage) const =0
shader_uniform_id find_uniform(const i_string &aName) const final
void generate_invoke(const i_shader_program &aProgram, shader_language aLanguage, i_string &aInvokes) const final
bool disabled() const final
shader_value_type value_type
neolib::jar< shader_uniform > uniform_list
void update_uniform_location(shader_uniform_id aUniform, shader_uniform_location aLocation) final
shader_type type() const final
const i_shader::uniform_list & uniforms() const final
i_shader::value_type abstract_value_type
void prepare_uniforms(const i_rendering_context &, i_shader_program &) override
void * handle(const i_shader_program &aProgram) const final
bool supports(vertex_buffer_type aBufferType) const override
void clear_uniform(shader_uniform_id aUniform) final
void update_uniform_storage(shader_uniform_id aUniform, shader_uniform_storage aStorage) final
bool enabled() const final
void clear_uniform_location(shader_uniform_id aUniform) final
shader(shader_type aType, std::string const &aName, bool aEnabled=true)
variable_list & in_variables()
const variable_list & out_variables() const final
i_shader_variable & add_variable(const i_shader_variable &aVariable) final
const i_string & name() const final
void set_uniform(shader_uniform_id aUniform, const abstract_value_type &aValue) final
void clear_variable(const i_string &aName) final
void clear_uniform_storage(shader_uniform_id aUniform) final
neolib::set< shader_variable > variable_list
void generate_code(const i_shader_program &aProgram, shader_language aLanguage, i_string &aOutput) const override
const variable_list & in_variables() const final
variable_list & out_variables()
bool uniforms_changed() const final
bool has_shared_uniforms() const final
shader_uniform_id create_uniform(const i_string &aName, bool aShared=false) final
uniform_list & uniforms()
virtual void replace_all(const i_string &aSearch, const i_string &aReplace)=0
void replace_all(const i_string &aSearch, const i_string &aReplace) final
shader_variable_qualifier
std::string to_string(note const &aNote)
basic_jar< T, vector< T >, cookie, MutexType > jar