Jump to content

  • Log In with Google      Sign In   
  • Create Account


Posted 28 September 2012 - 03:25 PM

hm, I see maybe that is not totally what you wanted, maybe you wanted a 'deferred storage' to be able to get and mutate your uniforms multiple times in a frame and only once actually upload it to the driver, so you wanted a way of managing that store ? which my solution doesn't provide of course. but it can maybe give you some ideas for ways to handle multiple types.

Also about the "nasty switch", check your assembly code, but it gets more optimized than anything that can be written by hand. Most people wrongly assume switches are stupid comparators that tries every value until finding the good one, but actually it uses optimal hashing / research or binary selection during code generation since all constants are integers and known.


Posted 28 September 2012 - 03:10 PM

edit: mistake. how do we delete posts ?


Posted 28 September 2012 - 03:08 PM

well, that didn't render too good. wth is that code tag, its not working at all ??
[source lang="cpp"]/*********************************************************************** File : shader_objects.hpp* Author: Lightness1024!* Date : 01/10/2009*********************************************************************/#ifndef SHADER_OBJECTS_HPP_INC_01_10_2009__184855354_#define SHADER_OBJECTS_HPP_INC_01_10_2009__184855354_ 1#include <manager_base.hpp>#include <boost/format.hpp>#include <boost/mpl/vector.hpp>#include <boost/mpl/contains.hpp>#include <boost/mpl/find.hpp>#include <boost/mpl/size.hpp>#include <boost/utility/enable_if.hpp>#include <boost/array.hpp>#include <boost/scoped_ptr.hpp>#include <stdio.h>#include <GL/glew.h>#include <iostream>#include <math/glm/virtrev/address.hpp>#include <gl_tbx.hpp>#include <tbx/config.hpp>extern boost::scoped_ptr<tbx::config> conf;namespace gfx{ namespace detail { char* get_shader_source(const char * szfilename); int load_program(char const* vtx_code_src, char const* frag_code_src); } namespace mpl = boost::mpl; // forwarders of type, one will just copy the input into the return value if the argument is of the // same type than the required output. the second will ignore the argument, and return a default constructed return type. // these function exist to enable compilation of function working of 'mat' when the argument is of type 'vec', which are incompatible. template< typename target_t, typename src_t > target_t forward(src_t const& val, typename boost::enable_if<boost::is_same<target_t, src_t> >::type* dummy = 0) { return val; } template< typename target_t, typename src_t > target_t forward(src_t const& val, typename boost::disable_if<boost::is_same<target_t, src_t> >::type* dummy = 0) { return target_t(); } //! represents a GLSL program that contains code for vertex and fragment shaders. class glsl_program { public: glsl_program(char const* vtx_code_src, char const* frag_code_src) { prog_glname_ = detail::load_program(vtx_code_src, frag_code_src); if (prog_glname_ == 0){ throw std::runtime_error( (boost::format("couldn't load shader files: %1% and/or %2%") % vtx_code_src % frag_code_src).str()); } } void set(){ glUseProgram(prog_glname_); last_set_prog_ = prog_glname_; } //! all uniform types we can manage: typedef mpl::vector< float, // 0 glm::vec2, // 1 glm::vec3, // 2 glm::vec4, // 3 glm::mat3, // 4 glm::mat4, int > uniform_types; typedef mpl::vector< glm::vec2, glm::vec3, glm::vec4> vec_types; typedef mpl::vector< glm::mat3, glm::mat4> mat_types; template< typename check_against_t > struct is_type_handled_uniform{ static bool const value = mpl::contains< uniform_types, check_against_t >::type::value; }; template< typename uniform_t > void update_uniform(char const* name, uniform_t const& value){ // check that the function is not used outside of its managed types (c.f. uniform_types): static_assert(( is_type_handled_uniform< uniform_t >::value && "YOU CANNOT COMPILE A CALL TO UPDATE_UNIFORM FUNCTION WITH A NON RECOGNIZED TYPE")); // other checks: assert(name && "CANNOT PASS NULL AS NAME"); assert(prog_glname_ > 0 && "CANNOT USE UPDATE_UNIFORM ON NON-LINKED PROGRAM"); assert(last_set_prog_ == prog_glname_ && "CANNOT USE UPDATE_UNIFORM ON NON-ATTACHED PROGRAM"); // type of functions from the gl specification: typedef void (*gl_func_fv_t) (GLint, GLsizei, GLfloat const*); // vectors typedef void (*gl_func_mat_t) (GLint, GLsizei, GLboolean, GLfloat const*); // matrices // define an array of functions for vectors: boost::array< gl_func_fv_t, 3 > const set_uniform_fv = {{glUniform2fv, glUniform3fv, glUniform4fv}}; // array of functions for matrices: boost::array< gl_func_mat_t, 2 > const set_uniform_mat = {{glUniformMatrix3fv, glUniformMatrix4fv}}; // find client's type position in sequence: size_t type_pos = mpl::find< uniform_types, uniform_t >::type::pos::value; // find uniform location in the shader program: size_t uniform_location = glGetUniformLocation(prog_glname_, name); if (uniform_location == -1) { std::string err_msg = (boost::format("attempt to modify uniform \"%1%\", but wasn't found in the shader program." "\n note: this is a hard error. you can make it soft by adding\"continue_on_uniform_issues=bool:true\" to your scud.conf") % name).str(); if (!conf->property<bool>("continue_on_uniform_issues", false)) throw std::runtime_error(err_msg); else std::cout << err_msg << std::endl; } // execute appropriate gl function to set the uniform: assert(type_pos <= mpl::size<uniform_types>::type::value); //std::cout << "type pos:" << type_pos << std::endl; switch (type_pos){ case 0: { // float GLfloat buildable = forward<GLfloat, uniform_t>(value); glUniform1f(uniform_location, buildable); break; } case 1: case 2: case 3: { // vecs // clamp uniform_t to a vec type to avoid build error typedef typename mpl::contains< vec_types, uniform_t >::type is_vec; typedef typename mpl::find< vec_types, uniform_t >::type found_among_vecs_iter; typedef typename mpl::deref<found_among_vecs_iter>::type found_among_vecs_t; typedef typename mpl::if_< is_vec, found_among_vecs_t, glm::vec4 >::type best_vec_t; best_vec_t buildable = forward<best_vec_t, uniform_t>(value); set_uniform_fv[type_pos - 1](uniform_location, 1, glm::address(buildable)); break; } case 4: case 5: { // mats typedef typename mpl::contains< mat_types, uniform_t >::type is_mat; typedef typename mpl::find< mat_types, uniform_t >::type found_among_mats_iter; typedef typename mpl::deref< found_among_mats_iter >::type found_among_mats_t; typedef typename mpl::if_< is_mat, found_among_mats_t, glm::mat4 >::type best_mat_t; best_mat_t buildable = forward<best_mat_t, uniform_t>(value); set_uniform_mat[type_pos - 4](uniform_location, 1, GL_FALSE, glm::address(buildable)); break; } case 6: { // int GLint buildable = forward<GLint, uniform_t>(value); glUniform1i(uniform_location, buildable); } } check_gl_error(SCUD_PROG_POS); } static void unset(){ glUseProgram(0); last_set_prog_ = 0; } private: GLuint prog_glname_; static GLuint last_set_prog_; };}#endif //SHADER_OBJECTS_HPP_INC_01_10_2009__184855354_[/source]