diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index c96986aa71..55863d42fb 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -925,53 +925,173 @@ update_shader_matrix_cache(Shader *shader, LVecBase4f *cache, int altered) { * these values. */ const LVecBase4f *GraphicsStateGuardian:: -fetch_specified_value(Shader::ShaderMatSpec &spec, const LVecBase4f *cache, LMatrix4f *scratch) { +fetch_specified_value(Shader::ShaderMatSpec &spec, const LVecBase4f *cache, LVecBase4f *scratch) { LVecBase3f v; const LVecBase4f *cache0 = cache + spec._cache_offset[0]; const LVecBase4f *cache1 = cache + spec._cache_offset[1]; + LMatrix4f &m = *(LMatrix4f *)scratch; + switch (spec._func) { case Shader::SMF_first: return cache0; case Shader::SMF_compose: - scratch->multiply(*(LMatrix4f *)cache0, *(LMatrix4f *)cache1); - return (LVecBase4f *)scratch; + m.multiply(*(LMatrix4f *)cache0, *(LMatrix4f *)cache1); + return (LVecBase4f *)&m; case Shader::SMF_transform_dlight: - *scratch = *(LMatrix4f *)cache0; + m = *(LMatrix4f *)cache0; v = (*(LMatrix4f *)cache1).xform_vec(cache0[2].get_xyz()); v.normalize(); - scratch->set_row(2, v); + m.set_row(2, v); v = (*(LMatrix4f *)cache1).xform_vec(cache0[3].get_xyz()); v.normalize(); - scratch->set_row(3, v); - return (LVecBase4f *)scratch; + m.set_row(3, v); + return (LVecBase4f *)&m; case Shader::SMF_transform_plight: { // Careful not to touch the w component, which contains the near value. - *scratch = *(LMatrix4f *)cache0; + m = *(LMatrix4f *)cache0; LPoint3f point = (*(LMatrix4f *)cache1).xform_point(cache0[2].get_xyz()); - (*scratch)(2, 0) = point[0]; - (*scratch)(2, 1) = point[1]; - (*scratch)(2, 2) = point[2]; - return (LVecBase4f *)scratch; + m(2, 0) = point[0]; + m(2, 1) = point[1]; + m(2, 2) = point[2]; + return (LVecBase4f *)&m; } case Shader::SMF_transform_slight: - *scratch = *(LMatrix4f *)cache0; - scratch->set_row(2, (*(LMatrix4f *)cache1).xform_point(cache0[2].get_xyz())); + m = *(LMatrix4f *)cache0; + m.set_row(2, (*(LMatrix4f *)cache1).xform_point(cache0[2].get_xyz())); v = (*(LMatrix4f *)cache1).xform_vec(cache0[3].get_xyz()); v.normalize(); - scratch->set_row(3, v); - return (LVecBase4f *)scratch; + m.set_row(3, v); + return (LVecBase4f *)&m; + + case Shader::SMF_shader_input_ptr: + return (const LVecBase4f *)fetch_ptr_parameter(spec, scratch); } // Should never get here - *scratch = LMatrix4f::ident_mat(); - return (LVecBase4f *)scratch; + m = LMatrix4f::ident_mat(); + return (LVecBase4f *)&m; +} + +/** + * Fetches a numeric shader input, doing conversion as necessary using the + * given amount of scratch space. + */ +const void *GraphicsStateGuardian:: +fetch_ptr_parameter(Shader::ShaderMatSpec &spec, LVecBase4f *scratch) { + Shader::ShaderPtrData ptr_data; + if (!_target_shader->get_shader_input_ptr(spec._arg[0], ptr_data)) { + return nullptr; + } + + nassertr(spec._num_components > 0, nullptr); + + int array_size = std::min(spec._array_count, (int)ptr_data._size / spec._num_components); + switch (spec._numeric_type) { + case Shader::SPT_float: + { + float *data = (float *)scratch; + + switch (ptr_data._type) { + case Shader::SPT_int: + // Convert int data to float data. + for (int i = 0; i < (array_size * spec._num_components); ++i) { + data[i] = (float)(((int*)ptr_data._ptr)[i]); + } + return data; + + case Shader::SPT_uint: + // Convert unsigned int data to float data. + for (int i = 0; i < (array_size * spec._num_components); ++i) { + data[i] = (float)(((unsigned int*)ptr_data._ptr)[i]); + } + return data; + + case Shader::SPT_double: + // Downgrade double data to float data. + for (int i = 0; i < (array_size * spec._num_components); ++i) { + data[i] = (float)(((double*)ptr_data._ptr)[i]); + } + return data; + + case Shader::SPT_float: + return (float *)ptr_data._ptr; + + default: +#ifndef NDEBUG + display_cat.error() + << "Invalid ShaderPtrData type " << (int)ptr_data._type + << " for shader input '" << spec._id._name << "'\n"; +#endif + return nullptr; + } + + return data; + } + break; + + case Shader::SPT_int: + if (ptr_data._type != Shader::SPT_int && + ptr_data._type != Shader::SPT_uint) { + display_cat.error() + << "Cannot pass floating-point data to integer shader input '" << spec._id._name << "'\n"; + + // Deactivate it to make sure the user doesn't get flooded with this + // error. + spec._dep = 0; + + } else { + return ptr_data._ptr; + } + break; + + case Shader::SPT_uint: + if (ptr_data._type != Shader::SPT_uint && + ptr_data._type != Shader::SPT_int) { + display_cat.error() + << "Cannot pass floating-point data to integer shader input '" << spec._id._name << "'\n"; + + // Deactivate it to make sure the user doesn't get flooded with this + // error. + spec._dep = 0; + return nullptr; + + } else { + return ptr_data._ptr; + } + break; + + case Shader::SPT_double: + display_cat.error() + << "Passing double-precision shader inputs to shaders is not currently supported\n"; + + // Deactivate it to make sure the user doesn't get flooded with this + // error. + spec._dep = 0; + break; + + case Shader::SPT_bool: + if (ptr_data._type == Shader::SPT_double) { + unsigned int *data = (unsigned int *)scratch; + for (int i = 0; i < (array_size * spec._num_components); ++i) { + data[i] = ((double *)ptr_data._ptr)[i] != 0; + } + return data; + } else { + return (float *)ptr_data._ptr; + } + + case Shader::SPT_unknown: + break; + } + + return nullptr; } /** diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index 4cd61f48a9..78d06f4551 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -337,7 +337,8 @@ public: virtual void clear(DrawableRegion *clearable); void update_shader_matrix_cache(Shader *shader, LVecBase4f *cache, int altered); - const LVecBase4f *fetch_specified_value(Shader::ShaderMatSpec &spec, const LVecBase4f *cache, LMatrix4f *scratch); + const LVecBase4f *fetch_specified_value(Shader::ShaderMatSpec &spec, const LVecBase4f *cache, LVecBase4f *scratch); + const void *fetch_ptr_parameter(Shader::ShaderMatSpec &spec, LVecBase4f *scratch); void fetch_specified_part(Shader::ShaderMatInput input, InternalName *name, LVecBase4f *into, int count = 1); void fetch_specified_member(const NodePath &np, CPT_InternalName member, diff --git a/panda/src/dxgsg9/dxShaderContext9.cxx b/panda/src/dxgsg9/dxShaderContext9.cxx index c5f3870771..da485cd50d 100644 --- a/panda/src/dxgsg9/dxShaderContext9.cxx +++ b/panda/src/dxgsg9/dxShaderContext9.cxx @@ -190,48 +190,10 @@ void DXShaderContext9:: issue_parameters(GSG *gsg, int altered) { #ifdef HAVE_CG if (_cg_program) { - - // Iterate through _ptr parameters - for (size_t i = 0; i < _shader->_ptr_spec.size(); ++i) { - const Shader::ShaderPtrSpec &spec = _shader->_ptr_spec[i]; - - if (altered & (spec._dep[0] | spec._dep[1])) { - const Shader::ShaderPtrData *ptr_data = gsg->fetch_ptr_parameter(spec); - - if (ptr_data == nullptr) { //the input is not contained in ShaderPtrData - release_resources(); - return; - } - - // Calculate how many elements to transfer; no more than it expects, - // but certainly no more than we have. - int input_size = std::min(abs(spec._dim[0] * spec._dim[1] * spec._dim[2]), (int)ptr_data->_size); - - CGparameter p = _cg_parameter_map[spec._id._seqno]; - switch (ptr_data->_type) { - case Shader::SPT_int: - cgSetParameterValueic(p, input_size, (int *)ptr_data->_ptr); - break; - - case Shader::SPT_double: - cgSetParameterValuedc(p, input_size, (double *)ptr_data->_ptr); - break; - - case Shader::SPT_float: - cgSetParameterValuefc(p, input_size, (float *)ptr_data->_ptr); - break; - - default: - dxgsg9_cat.error() - << spec._id._name << ": unrecognized parameter type\n"; - release_resources(); - return; - } - } - } - if (altered & _shader->_mat_deps) { - gsg->update_shader_matrix_cache(_shader, _mat_part_cache, altered); + if (altered & _shader->_mat_cache_deps) { + gsg->update_shader_matrix_cache(_shader, _mat_part_cache, altered); + } LMatrix4f scratch; diff --git a/panda/src/glstuff/glCgShaderContext_src.cxx b/panda/src/glstuff/glCgShaderContext_src.cxx index c3b0ee8ef4..50e72f86a4 100644 --- a/panda/src/glstuff/glCgShaderContext_src.cxx +++ b/panda/src/glstuff/glCgShaderContext_src.cxx @@ -535,7 +535,7 @@ issue_parameters(int altered) { // modified every frame and when we switch ShaderAttribs. if (altered & (Shader::SSD_shaderinputs | Shader::SSD_frame)) { // Iterate through _ptr parameters - for (int i = 0; i < (int)_shader->_ptr_spec.size(); ++i) { + /*for (int i = 0; i < (int)_shader->_ptr_spec.size(); ++i) { Shader::ShaderPtrSpec &spec = _shader->_ptr_spec[i]; const Shader::ShaderPtrData *ptr_data =_glgsg->fetch_ptr_parameter(spec); @@ -690,11 +690,13 @@ issue_parameters(int altered) { release_resources(); return; } - } + }*/ } if (altered & _shader->_mat_deps) { - _glgsg->update_shader_matrix_cache(_shader, _mat_part_cache, altered); + if (altered & _shader->_mat_cache_deps) { + _glgsg->update_shader_matrix_cache(_shader, _mat_part_cache, altered); + } LMatrix4f scratch; @@ -709,32 +711,79 @@ issue_parameters(int altered) { data += spec._offset; CGparameter p = _cg_parameter_map[spec._id._seqno]; - switch (spec._piece) { - case Shader::SMP_float: cgGLSetParameter1f(p, data[0]); continue; - case Shader::SMP_vec2: cgGLSetParameter2fv(p, data); continue; - case Shader::SMP_vec3: cgGLSetParameter3fv(p, data); continue; - case Shader::SMP_vec4: cgGLSetParameter4fv(p, data); continue; - case Shader::SMP_vec4_array: cgGLSetParameterArray4f(p, 0, spec._array_count, data); continue; - case Shader::SMP_mat4_whole: cgGLSetMatrixParameterfc(p, data); continue; - case Shader::SMP_mat4_array: cgGLSetMatrixParameterArrayfc(p, 0, spec._array_count, data); continue; - case Shader::SMP_mat4_transpose: cgGLSetMatrixParameterfr(p, data); continue; - case Shader::SMP_mat4_column: cgGLSetParameter4f(p, data[0], data[4], data[ 8], data[12]); continue; - case Shader::SMP_mat4_upper3x3: - { - LMatrix3f upper3(data[0], data[1], data[2], data[4], data[5], data[6], data[8], data[9], data[10]); - cgGLSetMatrixParameterfc(p, upper3.get_data()); - continue; + if (spec._numeric_type == Shader::SPT_float) { + switch (spec._piece) { + case Shader::SMP_scalar: cgGLSetParameter1f(p, data[0]); continue; + case Shader::SMP_vec2: cgGLSetParameter2fv(p, data); continue; + case Shader::SMP_vec3: cgGLSetParameter3fv(p, data); continue; + case Shader::SMP_vec4: cgGLSetParameter4fv(p, data); continue; + case Shader::SMP_scalar_array: cgGLSetParameterArray1f(p, 0, spec._array_count, data); continue; + case Shader::SMP_vec2_array: cgGLSetParameterArray2f(p, 0, spec._array_count, data); continue; + case Shader::SMP_vec3_array: cgGLSetParameterArray3f(p, 0, spec._array_count, data); continue; + case Shader::SMP_vec4_array: cgGLSetParameterArray4f(p, 0, spec._array_count, data); continue; + case Shader::SMP_mat3_whole: + case Shader::SMP_mat4_whole: cgGLSetMatrixParameterfc(p, data); continue; + case Shader::SMP_mat3_array: + case Shader::SMP_mat4_array: cgGLSetMatrixParameterArrayfc(p, 0, spec._array_count, data); continue; + case Shader::SMP_mat4_transpose: cgGLSetMatrixParameterfr(p, data); continue; + case Shader::SMP_mat4_column: cgGLSetParameter4f(p, data[0], data[4], data[ 8], data[12]); continue; + case Shader::SMP_mat4_upper3x3: + { + LMatrix3f upper3(data[0], data[1], data[2], data[4], data[5], data[6], data[8], data[9], data[10]); + cgGLSetMatrixParameterfc(p, upper3.get_data()); + continue; + } + case Shader::SMP_mat4_transpose3x3: + { + LMatrix3f upper3(data[0], data[1], data[2], data[4], data[5], data[6], data[8], data[9], data[10]); + cgGLSetMatrixParameterfr(p, upper3.get_data()); + continue; + } } - case Shader::SMP_mat4_transpose3x3: - { - LMatrix3f upper3(data[0], data[1], data[2], data[4], data[5], data[6], data[8], data[9], data[10]); - cgGLSetMatrixParameterfr(p, upper3.get_data()); - continue; + } + else if (spec._numeric_type == Shader::SPT_double) { + const double *datad = (const double *)data; + switch (spec._piece) { + case Shader::SMP_scalar: cgGLSetParameter1d(p, datad[0]); continue; + case Shader::SMP_vec2: cgGLSetParameter2dv(p, datad); continue; + case Shader::SMP_vec3: cgGLSetParameter3dv(p, datad); continue; + case Shader::SMP_vec4: cgGLSetParameter4dv(p, datad); continue; + case Shader::SMP_scalar_array: cgGLSetParameterArray1d(p, 0, spec._array_count, datad); continue; + case Shader::SMP_vec2_array: cgGLSetParameterArray2d(p, 0, spec._array_count, datad); continue; + case Shader::SMP_vec3_array: cgGLSetParameterArray3d(p, 0, spec._array_count, datad); continue; + case Shader::SMP_vec4_array: cgGLSetParameterArray4d(p, 0, spec._array_count, datad); continue; + case Shader::SMP_mat3_whole: + case Shader::SMP_mat4_whole: cgGLSetMatrixParameterdc(p, datad); continue; + case Shader::SMP_mat3_array: + case Shader::SMP_mat4_array: cgGLSetMatrixParameterArraydc(p, 0, spec._array_count, datad); continue; + case Shader::SMP_mat4_transpose: cgGLSetMatrixParameterdr(p, datad); continue; + case Shader::SMP_mat4_column: cgGLSetParameter4d(p, datad[0], datad[4], datad[ 8], datad[12]); continue; + case Shader::SMP_mat4_upper3x3: + { + LMatrix3d upper3(datad[0], datad[1], datad[2], datad[4], datad[5], datad[6], datad[8], datad[9], datad[10]); + cgGLSetMatrixParameterdc(p, upper3.get_data()); + continue; + } + case Shader::SMP_mat4_transpose3x3: + { + LMatrix3d upper3(datad[0], datad[1], datad[2], datad[4], datad[5], datad[6], datad[8], datad[9], datad[10]); + cgGLSetMatrixParameterdr(p, upper3.get_data()); + continue; + } + } + } + else if (spec._numeric_type == Shader::SPT_int || spec._numeric_type == Shader::SPT_uint) { + switch (spec._piece) { + case Shader::SMP_scalar_array: + case Shader::SMP_scalar: cgSetParameter1i(p, ((int *)data)[0]); continue; + case Shader::SMP_vec2_array: + case Shader::SMP_vec2: cgSetParameter2iv(p, (int *)data); continue; + case Shader::SMP_vec3_array: + case Shader::SMP_vec3: cgSetParameter3iv(p, (int *)data); continue; + case Shader::SMP_vec4_array: + case Shader::SMP_vec4: cgSetParameter4iv(p, (int *)data); continue; + default: assert(false); } - case Shader::SMP_int: cgSetParameter1i(p, ((const int *)data)[0]); continue; - case Shader::SMP_ivec2: cgSetParameter2iv(p, (const int *)data); continue; - case Shader::SMP_ivec3: cgSetParameter3iv(p, (const int *)data); continue; - case Shader::SMP_ivec4: cgSetParameter4iv(p, (const int *)data); continue; } } } diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index fcdee77be1..fcf2837348 100644 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -208,7 +208,7 @@ parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, GLenum param_t // We'll permit this too, simply because we can support it. switch (param_type) { case GL_FLOAT: - bind._piece = Shader::SMP_float; + bind._piece = Shader::SMP_scalar; break; case GL_FLOAT_VEC2: bind._piece = Shader::SMP_vec2; @@ -404,7 +404,7 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext param_count = 0; _glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORMS, ¶m_count); - _shader->_ptr_spec.clear(); + //_shader->_ptr_spec.clear(); _shader->_mat_spec.clear(); _shader->_tex_spec.clear(); for (int i = 0; i < param_count; ++i) { @@ -421,6 +421,7 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext } _mat_part_cache = new LVecBase4f[_shader->cp_get_mat_cache_size()]; + _mat_scratch_space = new LVecBase4f[_shader->cp_get_mat_scratch_size()]; } /** @@ -478,6 +479,8 @@ reflect_attribute(int i, char *name_buffer, GLsizei name_buflen) { case GL_BOOL_VEC2: case GL_BOOL_VEC3: case GL_BOOL_VEC4: + bind._numeric_type = Shader::SPT_bool; + break; case GL_UNSIGNED_INT: case GL_UNSIGNED_INT_VEC2: case GL_UNSIGNED_INT_VEC3: @@ -1120,7 +1123,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { GLCAT.error() << "p3d_Material.shininess should be float\n"; } - bind._piece = Shader::SMP_float; + bind._piece = Shader::SMP_scalar; bind._offset = 15; _shader->cp_add_mat_spec(bind); return; @@ -1131,7 +1134,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { << "p3d_Material.roughness should be float\n"; } bind._part[0] = Shader::SMO_attr_material2; - bind._piece = Shader::SMP_float; + bind._piece = Shader::SMP_scalar; bind._offset = 7; _shader->cp_add_mat_spec(bind); return; @@ -1142,7 +1145,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { << "p3d_Material.metallic should be bool or float\n"; } bind._part[0] = Shader::SMO_attr_material2; - bind._piece = Shader::SMP_float; + bind._piece = Shader::SMP_scalar; bind._offset = 4; _shader->cp_add_mat_spec(bind); return; @@ -1153,7 +1156,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { << "p3d_Material.refractiveIndex should be float\n"; } bind._part[0] = Shader::SMO_attr_material2; - bind._piece = Shader::SMP_float; + bind._piece = Shader::SMP_scalar; bind._offset = 5; _shader->cp_add_mat_spec(bind); return; @@ -1244,7 +1247,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { bind._part[0] = Shader::SMO_attr_fog; if (param_type == GL_FLOAT) { - bind._piece = Shader::SMP_float; + bind._piece = Shader::SMP_scalar; } else { GLCAT.error() << "p3d_Fog.density should be float\n"; @@ -1255,7 +1258,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { bind._part[0] = Shader::SMO_attr_fog; if (param_type == GL_FLOAT) { - bind._piece = Shader::SMP_float; + bind._piece = Shader::SMP_scalar; bind._offset = 1; } else { GLCAT.error() @@ -1267,7 +1270,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { bind._part[0] = Shader::SMO_attr_fog; if (param_type == GL_FLOAT) { - bind._piece = Shader::SMP_float; + bind._piece = Shader::SMP_scalar; bind._offset = 2; } else { GLCAT.error() @@ -1279,7 +1282,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { bind._part[0] = Shader::SMO_attr_fog; if (param_type == GL_FLOAT) { - bind._piece = Shader::SMP_float; + bind._piece = Shader::SMP_scalar; bind._offset = 3; } else { GLCAT.error() @@ -1354,7 +1357,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { switch (param_type) { case GL_FLOAT: - bind._piece = Shader::SMP_float; + bind._piece = Shader::SMP_scalar; break; case GL_FLOAT_VEC2: @@ -1442,7 +1445,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { return; } else if (noprefix == "FrameTime") { - bind._piece = Shader::SMP_float; + bind._piece = Shader::SMP_scalar; bind._func = Shader::SMF_first; bind._part[0] = Shader::SMO_frame_time; bind._part[1] = Shader::SMO_identity; @@ -1450,7 +1453,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { return; } else if (noprefix == "DeltaFrameTime") { - bind._piece = Shader::SMP_float; + bind._piece = Shader::SMP_scalar; bind._func = Shader::SMF_first; bind._part[0] = Shader::SMO_frame_delta; bind._part[1] = Shader::SMO_identity; @@ -1596,7 +1599,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { bind._id = arg_id; switch (param_type) { case GL_FLOAT: - bind._piece = Shader::SMP_float; + bind._piece = Shader::SMP_scalar; break; case GL_FLOAT_VEC2: bind._piece = Shader::SMP_vec2; @@ -1628,59 +1631,106 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { case GL_UNSIGNED_INT_VEC2: case GL_UNSIGNED_INT_VEC3: case GL_UNSIGNED_INT_VEC4: { - Shader::ShaderPtrSpec bind; + Shader::ShaderMatSpec bind; bind._id = arg_id; - switch (param_type) { - case GL_BOOL: - case GL_INT: - case GL_UNSIGNED_INT: - case GL_FLOAT: bind._dim[1] = 1; break; - case GL_BOOL_VEC2: - case GL_INT_VEC2: - case GL_UNSIGNED_INT_VEC2: - case GL_FLOAT_VEC2: bind._dim[1] = 2; break; - case GL_BOOL_VEC3: - case GL_INT_VEC3: - case GL_UNSIGNED_INT_VEC3: - case GL_FLOAT_VEC3: bind._dim[1] = 3; break; - case GL_BOOL_VEC4: - case GL_INT_VEC4: - case GL_UNSIGNED_INT_VEC4: - case GL_FLOAT_VEC4: bind._dim[1] = 4; break; - case GL_FLOAT_MAT3: bind._dim[1] = 9; break; - case GL_FLOAT_MAT4: bind._dim[1] = 16; break; - } + bind._func = Shader::SMF_shader_input_ptr; switch (param_type) { case GL_BOOL: + bind._piece = Shader::SMP_scalar; + bind._numeric_type = Shader::SPT_bool; + bind._num_components = 1; + break; case GL_BOOL_VEC2: + bind._piece = Shader::SMP_vec2; + bind._numeric_type = Shader::SPT_bool; + bind._num_components = 2; + break; case GL_BOOL_VEC3: + bind._piece = Shader::SMP_vec3; + bind._numeric_type = Shader::SPT_bool; + bind._num_components = 3; + break; case GL_BOOL_VEC4: + bind._piece = Shader::SMP_vec4; + bind._numeric_type = Shader::SPT_bool; + bind._num_components = 4; + break; case GL_UNSIGNED_INT: + bind._piece = Shader::SMP_scalar; + bind._numeric_type = Shader::SPT_uint; + bind._num_components = 1; + break; case GL_UNSIGNED_INT_VEC2: + bind._piece = Shader::SMP_vec2; + bind._numeric_type = Shader::SPT_uint; + bind._num_components = 2; + break; case GL_UNSIGNED_INT_VEC3: + bind._piece = Shader::SMP_vec3; + bind._numeric_type = Shader::SPT_uint; + bind._num_components = 3; + break; case GL_UNSIGNED_INT_VEC4: - bind._type = Shader::SPT_uint; + bind._piece = Shader::SMP_vec4; + bind._numeric_type = Shader::SPT_uint; + bind._num_components = 4; break; case GL_INT: + bind._piece = Shader::SMP_scalar; + bind._numeric_type = Shader::SPT_int; + bind._num_components = 1; + break; case GL_INT_VEC2: + bind._piece = Shader::SMP_vec2; + bind._numeric_type = Shader::SPT_int; + bind._num_components = 2; + break; case GL_INT_VEC3: + bind._piece = Shader::SMP_vec3; + bind._numeric_type = Shader::SPT_int; + bind._num_components = 3; + break; case GL_INT_VEC4: - bind._type = Shader::SPT_int; + bind._piece = Shader::SMP_vec4; + bind._numeric_type = Shader::SPT_int; + bind._num_components = 4; break; case GL_FLOAT: + bind._piece = Shader::SMP_scalar; + bind._numeric_type = Shader::SPT_float; + bind._num_components = 1; + break; case GL_FLOAT_VEC2: + bind._piece = Shader::SMP_vec2; + bind._numeric_type = Shader::SPT_float; + bind._num_components = 2; + break; case GL_FLOAT_VEC3: + bind._piece = Shader::SMP_vec3; + bind._numeric_type = Shader::SPT_float; + bind._num_components = 3; + break; case GL_FLOAT_VEC4: + bind._piece = Shader::SMP_vec4; + bind._numeric_type = Shader::SPT_float; + bind._num_components = 4; + break; case GL_FLOAT_MAT3: + bind._piece = Shader::SMP_mat3_whole; + bind._numeric_type = Shader::SPT_float; + bind._num_components = 9; + break; case GL_FLOAT_MAT4: - bind._type = Shader::SPT_float; + bind._piece = Shader::SMP_mat4_whole; + bind._numeric_type = Shader::SPT_float; + bind._num_components = 16; break; } - bind._arg = InternalName::make(param_name); - bind._dim[0] = 1; - bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame; - bind._dep[1] = Shader::SSD_NONE; - _shader->_ptr_spec.push_back(bind); + bind._part[0] = Shader::SMO_INVALID; + bind._part[1] = Shader::SMO_INVALID; + bind._arg[0] = InternalName::make(param_name); + bind._arg[1] = nullptr; + _shader->cp_add_mat_spec(bind); return; } case GL_IMAGE_2D: @@ -1772,55 +1822,107 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) { case GL_FLOAT_VEC4: case GL_FLOAT_MAT3: case GL_FLOAT_MAT4: { - Shader::ShaderPtrSpec bind; + Shader::ShaderMatSpec bind; bind._id = arg_id; - switch (param_type) { - case GL_BOOL: - case GL_INT: - case GL_FLOAT: bind._dim[1] = 1; break; - case GL_BOOL_VEC2: - case GL_INT_VEC2: - case GL_FLOAT_VEC2: bind._dim[1] = 2; break; - case GL_BOOL_VEC3: - case GL_INT_VEC3: - case GL_FLOAT_VEC3: bind._dim[1] = 3; break; - case GL_BOOL_VEC4: - case GL_INT_VEC4: - case GL_FLOAT_VEC4: bind._dim[1] = 4; break; - case GL_FLOAT_MAT3: bind._dim[1] = 9; break; - case GL_FLOAT_MAT4: bind._dim[1] = 16; break; - } + bind._func = Shader::SMF_shader_input_ptr; switch (param_type) { case GL_BOOL: + bind._piece = Shader::SMP_scalar_array; + bind._numeric_type = Shader::SPT_uint; + bind._num_components = 1; + break; case GL_BOOL_VEC2: + bind._piece = Shader::SMP_vec2_array; + bind._numeric_type = Shader::SPT_uint; + bind._num_components = 2; + break; case GL_BOOL_VEC3: + bind._piece = Shader::SMP_vec3_array; + bind._numeric_type = Shader::SPT_uint; + bind._num_components = 3; + break; case GL_BOOL_VEC4: + bind._piece = Shader::SMP_vec4_array; + bind._numeric_type = Shader::SPT_uint; + bind._num_components = 4; + break; case GL_UNSIGNED_INT: + bind._piece = Shader::SMP_scalar_array; + bind._numeric_type = Shader::SPT_uint; + bind._num_components = 1; + break; case GL_UNSIGNED_INT_VEC2: + bind._piece = Shader::SMP_vec2_array; + bind._numeric_type = Shader::SPT_uint; + bind._num_components = 2; + break; case GL_UNSIGNED_INT_VEC3: + bind._piece = Shader::SMP_vec3_array; + bind._numeric_type = Shader::SPT_uint; + bind._num_components = 3; + break; case GL_UNSIGNED_INT_VEC4: - bind._type = Shader::SPT_uint; + bind._piece = Shader::SMP_vec4_array; + bind._numeric_type = Shader::SPT_uint; + bind._num_components = 4; break; case GL_INT: + bind._piece = Shader::SMP_scalar_array; + bind._numeric_type = Shader::SPT_int; + bind._num_components = 1; + break; case GL_INT_VEC2: + bind._piece = Shader::SMP_vec2_array; + bind._numeric_type = Shader::SPT_int; + bind._num_components = 2; + break; case GL_INT_VEC3: + bind._piece = Shader::SMP_vec3_array; + bind._numeric_type = Shader::SPT_int; + bind._num_components = 3; + break; case GL_INT_VEC4: - bind._type = Shader::SPT_int; + bind._piece = Shader::SMP_vec4_array; + bind._numeric_type = Shader::SPT_int; + bind._num_components = 4; break; case GL_FLOAT: + bind._piece = Shader::SMP_scalar_array; + bind._numeric_type = Shader::SPT_float; + bind._num_components = 1; + break; case GL_FLOAT_VEC2: + bind._piece = Shader::SMP_vec2_array; + bind._numeric_type = Shader::SPT_float; + bind._num_components = 2; + break; case GL_FLOAT_VEC3: + bind._piece = Shader::SMP_vec3_array; + bind._numeric_type = Shader::SPT_float; + bind._num_components = 3; + break; case GL_FLOAT_VEC4: + bind._piece = Shader::SMP_vec4_array; + bind._numeric_type = Shader::SPT_float; + bind._num_components = 4; + break; case GL_FLOAT_MAT3: + bind._piece = Shader::SMP_mat3_array; + bind._numeric_type = Shader::SPT_float; + bind._num_components = 9; + break; case GL_FLOAT_MAT4: - bind._type = Shader::SPT_float; + bind._piece = Shader::SMP_mat4_array; + bind._numeric_type = Shader::SPT_float; + bind._num_components = 16; break; } - bind._arg = InternalName::make(param_name); - bind._dim[0] = param_size; - bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame; - bind._dep[1] = Shader::SSD_NONE; - _shader->_ptr_spec.push_back(bind); + bind._part[0] = Shader::SMO_INVALID; + bind._part[1] = Shader::SMO_INVALID; + bind._arg[0] = InternalName::make(param_name); + bind._arg[1] = nullptr; + bind._array_count = param_size; + _shader->cp_add_mat_spec(bind); return; } default: @@ -1967,6 +2069,7 @@ CLP(ShaderContext):: ~CLP(ShaderContext)() { // Don't call release_resources; we may not have an active context. delete[] _mat_part_cache; + delete[] _mat_scratch_space; } /** @@ -2170,7 +2273,7 @@ issue_parameters(int altered) { } // Iterate through _ptr parameters - for (int i = 0; i < (int)_shader->_ptr_spec.size(); ++i) { + /*for (int i = 0; i < (int)_shader->_ptr_spec.size(); ++i) { Shader::ShaderPtrSpec &spec = _shader->_ptr_spec[i]; Shader::ShaderPtrData ptr_data; @@ -2293,51 +2396,83 @@ issue_parameters(int altered) { default: continue; } - } + }*/ } if (altered & _shader->_mat_deps) { - _glgsg->update_shader_matrix_cache(_shader, _mat_part_cache, altered); - - LMatrix4f scratch; + if (altered & _shader->_mat_cache_deps) { + _glgsg->update_shader_matrix_cache(_shader, _mat_part_cache, altered); + } for (Shader::ShaderMatSpec &spec : _shader->_mat_spec) { if ((altered & spec._dep) == 0) { continue; } - const LVecBase4f *val = _glgsg->fetch_specified_value(spec, _mat_part_cache, &scratch); + const LVecBase4f *val = _glgsg->fetch_specified_value(spec, _mat_part_cache, _mat_scratch_space); if (!val) continue; const float *data = val->get_data(); data += spec._offset; GLint p = spec._id._seqno; - switch (spec._piece) { - case Shader::SMP_float: _glgsg->_glUniform1fv(p, 1, data); continue; - case Shader::SMP_vec2: _glgsg->_glUniform2fv(p, 1, data); continue; - case Shader::SMP_vec3: _glgsg->_glUniform3fv(p, 1, data); continue; - case Shader::SMP_vec4: _glgsg->_glUniform4fv(p, 1, data); continue; - case Shader::SMP_vec4_array: _glgsg->_glUniform4fv(p, spec._array_count, data); continue; - case Shader::SMP_mat4_whole: _glgsg->_glUniformMatrix4fv(p, 1, GL_FALSE, data); continue; - case Shader::SMP_mat4_array: _glgsg->_glUniformMatrix4fv(p, spec._array_count, GL_FALSE, data); continue; - case Shader::SMP_mat4_transpose: _glgsg->_glUniformMatrix4fv(p, 1, GL_TRUE, data); continue; - case Shader::SMP_mat4_column: _glgsg->_glUniform4f(p, data[0], data[4], data[8], data[12]); continue; - case Shader::SMP_mat4_upper3x3: - { - LMatrix3f upper3(data[0], data[1], data[2], data[4], data[5], data[6], data[8], data[9], data[10]); - _glgsg->_glUniformMatrix3fv(p, 1, false, upper3.get_data()); - continue; + if (spec._numeric_type == Shader::SPT_float) { + switch (spec._piece) { + case Shader::SMP_scalar: _glgsg->_glUniform1fv(p, 1, data); continue; + case Shader::SMP_vec2: _glgsg->_glUniform2fv(p, 1, data); continue; + case Shader::SMP_vec3: _glgsg->_glUniform3fv(p, 1, data); continue; + case Shader::SMP_vec4: _glgsg->_glUniform4fv(p, 1, data); continue; + case Shader::SMP_scalar_array: _glgsg->_glUniform1fv(p, spec._array_count, data); continue; + case Shader::SMP_vec2_array: _glgsg->_glUniform2fv(p, spec._array_count, data); continue; + case Shader::SMP_vec3_array: _glgsg->_glUniform3fv(p, spec._array_count, data); continue; + case Shader::SMP_vec4_array: _glgsg->_glUniform4fv(p, spec._array_count, data); continue; + case Shader::SMP_mat3_whole: _glgsg->_glUniformMatrix3fv(p, 1, GL_FALSE, data); continue; + case Shader::SMP_mat3_array: _glgsg->_glUniformMatrix3fv(p, spec._array_count, GL_FALSE, data); continue; + case Shader::SMP_mat4_whole: _glgsg->_glUniformMatrix4fv(p, 1, GL_FALSE, data); continue; + case Shader::SMP_mat4_array: _glgsg->_glUniformMatrix4fv(p, spec._array_count, GL_FALSE, data); continue; + case Shader::SMP_mat4_transpose: _glgsg->_glUniformMatrix4fv(p, 1, GL_TRUE, data); continue; + case Shader::SMP_mat4_column: _glgsg->_glUniform4f(p, data[0], data[4], data[8], data[12]); continue; + case Shader::SMP_mat4_upper3x3: + { + LMatrix3f upper3(data[0], data[1], data[2], data[4], data[5], data[6], data[8], data[9], data[10]); + _glgsg->_glUniformMatrix3fv(p, 1, false, upper3.get_data()); + continue; + } + case Shader::SMP_mat4_transpose3x3: + { + LMatrix3f upper3(data[0], data[1], data[2], data[4], data[5], data[6], data[8], data[9], data[10]); + _glgsg->_glUniformMatrix3fv(p, 1, true, upper3.get_data()); + continue; + } } - case Shader::SMP_mat4_transpose3x3: - { - LMatrix3f upper3(data[0], data[1], data[2], data[4], data[5], data[6], data[8], data[9], data[10]); - _glgsg->_glUniformMatrix3fv(p, 1, true, upper3.get_data()); - continue; + } + else if (spec._numeric_type == Shader::SPT_int) { + switch (spec._piece) { + case Shader::SMP_scalar: _glgsg->_glUniform1iv(p, 1, (const GLint *)data); continue; + case Shader::SMP_vec2: _glgsg->_glUniform2iv(p, 1, (const GLint *)data); continue; + case Shader::SMP_vec3: _glgsg->_glUniform3iv(p, 1, (const GLint *)data); continue; + case Shader::SMP_vec4: _glgsg->_glUniform4iv(p, 1, (const GLint *)data); continue; + case Shader::SMP_scalar_array: _glgsg->_glUniform1iv(p, spec._array_count, (const GLint *)data); continue; + case Shader::SMP_vec2_array: _glgsg->_glUniform2iv(p, spec._array_count, (const GLint *)data); continue; + case Shader::SMP_vec3_array: _glgsg->_glUniform3iv(p, spec._array_count, (const GLint *)data); continue; + case Shader::SMP_vec4_array: _glgsg->_glUniform4iv(p, spec._array_count, (const GLint *)data); continue; + default: assert(false); } - case Shader::SMP_int: _glgsg->_glUniform1i(p, ((int *)data)[0]); continue; - case Shader::SMP_ivec2: _glgsg->_glUniform2iv(p, 1, (int *)data); continue; - case Shader::SMP_ivec3: _glgsg->_glUniform3iv(p, 1, (int *)data); continue; - case Shader::SMP_ivec4: _glgsg->_glUniform4iv(p, 1, (int *)data); continue; + } + else if (spec._numeric_type == Shader::SPT_uint || spec._numeric_type == Shader::SPT_bool) { + switch (spec._piece) { + case Shader::SMP_scalar: _glgsg->_glUniform1uiv(p, 1, (const GLuint *)data); continue; + case Shader::SMP_vec2: _glgsg->_glUniform2uiv(p, 1, (const GLuint *)data); continue; + case Shader::SMP_vec3: _glgsg->_glUniform3uiv(p, 1, (const GLuint *)data); continue; + case Shader::SMP_vec4: _glgsg->_glUniform4uiv(p, 1, (const GLuint *)data); continue; + case Shader::SMP_scalar_array: _glgsg->_glUniform1uiv(p, spec._array_count, (const GLuint *)data); continue; + case Shader::SMP_vec2_array: _glgsg->_glUniform2uiv(p, spec._array_count, (const GLuint *)data); continue; + case Shader::SMP_vec3_array: _glgsg->_glUniform3uiv(p, spec._array_count, (const GLuint *)data); continue; + case Shader::SMP_vec4_array: _glgsg->_glUniform4uiv(p, spec._array_count, (const GLuint *)data); continue; + default: assert(false); + } + } + else { + nassert_raise("double-precision uniform passing not supported"); } } } diff --git a/panda/src/glstuff/glShaderContext_src.h b/panda/src/glstuff/glShaderContext_src.h index b42fa97538..e5616cb975 100644 --- a/panda/src/glstuff/glShaderContext_src.h +++ b/panda/src/glstuff/glShaderContext_src.h @@ -113,6 +113,7 @@ private: pvector _glsl_img_inputs; LVecBase4f *_mat_part_cache = nullptr; + LVecBase4f *_mat_scratch_space = nullptr; CLP(GraphicsStateGuardian) *_glgsg; diff --git a/panda/src/gobj/shader.cxx b/panda/src/gobj/shader.cxx index 067ab9527c..286543aba8 100644 --- a/panda/src/gobj/shader.cxx +++ b/panda/src/gobj/shader.cxx @@ -602,6 +602,9 @@ cp_add_mat_spec(ShaderMatSpec &spec) { int num_parts = (spec._func != SMF_first) ? 2 : 1; for (int p = 0; p < num_parts; ++p) { + if (spec._part[p] == SMO_INVALID) { + continue; + } int dep = cp_dependency(spec._part[p]); spec._dep |= dep; @@ -724,10 +727,19 @@ cp_add_mat_spec(ShaderMatSpec &spec) { assert(part._size == 4); } + _mat_cache_deps |= part._dep; _mat_parts.push_back(std::move(part)); } spec._cache_offset[p] = offset + begin[p]; } + if (spec._func == SMF_shader_input_ptr) { + _mat_scratch_size = std::max(_mat_scratch_size, spec._array_count); + + // We specify SSD_frame because a PTA may be modified by the app from + // frame to frame, and we have no way to know. So, we must respecify a + // PTA at least once every frame. + spec._dep |= SSD_general | SSD_shaderinputs | SSD_frame; + } _mat_spec.push_back(spec); _mat_deps |= spec._dep; @@ -746,6 +758,15 @@ cp_get_mat_cache_size() const { return size; } +/** + * Returns the total amount of scratch space required to fetch the largest + * shader input of this shader. + */ +size_t Shader:: +cp_get_mat_scratch_size() const { + return _mat_scratch_size; +} + #ifdef HAVE_CG /** * @@ -1483,7 +1504,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) { if (!cp_errchk_parameter_float(p, 1, 1)) { return false; } - bind._piece = SMP_float; + bind._piece = SMP_scalar; bind._part[0] = SMO_frame_time; bind._arg[0] = nullptr; @@ -1635,25 +1656,25 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) { case SAC_matrix: case SAC_scalar: case SAC_array: { - if (!cp_errchk_parameter_ptr(p)) + if (!cp_errchk_parameter_ptr(p)) { return false; + } - ShaderPtrSpec bind; - bind._id = p._id; - bind._arg = kinputname; - bind._info = p; - - // We specify SSD_frame because a PTA may be modified by the app from - // frame to frame, and we have no way to know. So, we must respecify a - // PTA at least once every frame. - bind._dep[0] = SSD_general | SSD_shaderinputs | SSD_frame; - bind._dep[1] = SSD_NONE; - - memcpy(bind._dim,arg_dim,sizeof(int)*3); + ShaderMatSpec bind; + bind._id = p._id; + bind._func = SMF_shader_input_ptr; + bind._part[0] = SMO_INVALID; + bind._part[1] = SMO_INVALID; + bind._arg[0] = kinputname; + bind._arg[1] = nullptr; + bind._array_count = arg_dim[0] * arg_dim[1]; + bind._num_components = arg_dim[2]; + bind._numeric_type = p._numeric_type; + bind._piece = (ShaderMatPiece)(SMP_scalar + (arg_dim[2] - 1)); // if dim[0] = -1, glShaderContext will not check the param size - if (k_prefix) bind._dim[0] = -1; - _ptr_spec.push_back(bind); + //if (k_prefix) bind._dim[0] = -1; + cp_add_mat_spec(bind); return true; } @@ -2285,11 +2306,6 @@ cg_analyze_shader(const ShaderCaps &caps) { _tex_spec[i]._id._seqno = seqno++; } - for (size_t i = 0; i < _ptr_spec.size(); ++i) { - _ptr_spec[i]._id._seqno = seqno++; - _ptr_spec[i]._info._id = _ptr_spec[i]._id; - } - /* // The following code is present to work around a bug in the Cg compiler. // It does not generate correct code for shadow map lookups when using arbfp1. @@ -2452,9 +2468,8 @@ cg_compile_for(const ShaderCaps &caps, CGcontext context, size_t n_mat = _mat_spec.size(); size_t n_tex = _tex_spec.size(); size_t n_var = _var_spec.size(); - size_t n_ptr = _ptr_spec.size(); - map.resize(n_mat + n_tex + n_var + n_ptr); + map.resize(n_mat + n_tex + n_var); // This is a bit awkward, we have to go in and seperate out the combined // program, since all the parameter bindings have changed. @@ -2513,19 +2528,6 @@ cg_compile_for(const ShaderCaps &caps, CGcontext context, map[id._seqno] = p; } - for (size_t i = 0; i < n_ptr; ++i) { - const ShaderArgId &id = _ptr_spec[i]._id; - map[id._seqno] = cgGetNamedParameter(programs_by_type[id._type], id._name.c_str()); - - if (shader_cat.is_debug()) { - const char *resource = cgGetParameterResourceName(map[id._seqno]); - if (resource != nullptr) { - shader_cat.debug() << "Uniform ptr parameter " << id._name - << " is bound to resource " << resource << "\n"; - } - } - } - // Transfer ownership of the compiled shader. if (_cg_vprogram != 0) { cgDestroyProgram(_cg_vprogram); diff --git a/panda/src/gobj/shader.h b/panda/src/gobj/shader.h index dedff6c542..196ede0980 100644 --- a/panda/src/gobj/shader.h +++ b/panda/src/gobj/shader.h @@ -292,21 +292,22 @@ public: }; enum ShaderMatPiece { - SMP_float, + SMP_scalar, SMP_vec2, SMP_vec3, SMP_vec4, + SMP_scalar_array, + SMP_vec2_array, + SMP_vec3_array, SMP_vec4_array, + SMP_mat3_whole, + SMP_mat3_array, SMP_mat4_whole, SMP_mat4_array, SMP_mat4_transpose, SMP_mat4_column, SMP_mat4_upper3x3, SMP_mat4_transpose3x3, - SMP_int, - SMP_ivec2, - SMP_ivec3, - SMP_ivec4, }; enum ShaderStateDep { @@ -339,6 +340,7 @@ public: SMF_transform_dlight, SMF_transform_plight, SMF_transform_slight, + SMF_shader_input_ptr, }; struct ShaderArgId { @@ -352,6 +354,7 @@ public: SPT_double, SPT_int, SPT_uint, + SPT_bool, SPT_unknown }; @@ -443,6 +446,8 @@ public: ShaderMatPiece _piece; int _offset = 0; int _array_count = 1; + int _num_components; + ShaderPtrType _numeric_type = SPT_float; }; struct ShaderTexSpec { @@ -547,6 +552,7 @@ public: int cp_dependency(ShaderMatInput inp); void cp_add_mat_spec(ShaderMatSpec &spec); size_t cp_get_mat_cache_size() const; + size_t cp_get_mat_scratch_size() const; #ifdef HAVE_CG void cg_recurse_parameters(CGparameter parameter, @@ -606,13 +612,13 @@ public: #endif public: - pvector _ptr_spec; pvector _mat_spec; pvector _tex_spec; pvector _var_spec; pvector _mat_parts; + int _mat_cache_deps = 0; int _mat_deps = 0; - int _mat_cache_size = 0; + int _mat_scratch_size = 4; bool _error_flag; ShaderFile _text; diff --git a/tests/display/test_glsl_shader.py b/tests/display/test_glsl_shader.py index 6fbd917e89..36fe1e791a 100644 --- a/tests/display/test_glsl_shader.py +++ b/tests/display/test_glsl_shader.py @@ -463,6 +463,26 @@ def test_glsl_pta_ivec4(gsg): run_glsl_test(gsg, code, preamble, {'pta': pta}) +def test_glsl_pta_mat3(gsg): + pta = core.PTA_LMatrix3f(( + (0, 1, 2, 3, 4, 5, 6, 7, 8), + (9, 10, 11, 12, 13, 14, 15, 16, 17), + )) + + preamble = """ + uniform mat3 pta[2]; + """ + code = """ + assert(pta[0][0] == vec3(0, 1, 2)); + assert(pta[0][1] == vec3(3, 4, 5)); + assert(pta[0][2] == vec3(6, 7, 8)); + assert(pta[1][0] == vec3(9, 10, 11)); + assert(pta[1][1] == vec3(12, 13, 14)); + assert(pta[1][2] == vec3(15, 16, 17)); + """ + run_glsl_test(gsg, code, preamble, {'pta': pta}) + + def test_glsl_pta_mat4(gsg): pta = core.PTA_LMatrix4f(( (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15),