shader: Unify ShaderPtrSpec and ShaderMatSpec mechanisms

This commit is contained in:
rdb 2024-08-22 22:44:03 +02:00
parent 99f4034701
commit 99225dfaef
9 changed files with 524 additions and 228 deletions

View File

@ -925,53 +925,173 @@ update_shader_matrix_cache(Shader *shader, LVecBase4f *cache, int altered) {
* these values. * these values.
*/ */
const LVecBase4f *GraphicsStateGuardian:: 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; LVecBase3f v;
const LVecBase4f *cache0 = cache + spec._cache_offset[0]; const LVecBase4f *cache0 = cache + spec._cache_offset[0];
const LVecBase4f *cache1 = cache + spec._cache_offset[1]; const LVecBase4f *cache1 = cache + spec._cache_offset[1];
LMatrix4f &m = *(LMatrix4f *)scratch;
switch (spec._func) { switch (spec._func) {
case Shader::SMF_first: case Shader::SMF_first:
return cache0; return cache0;
case Shader::SMF_compose: case Shader::SMF_compose:
scratch->multiply(*(LMatrix4f *)cache0, *(LMatrix4f *)cache1); m.multiply(*(LMatrix4f *)cache0, *(LMatrix4f *)cache1);
return (LVecBase4f *)scratch; return (LVecBase4f *)&m;
case Shader::SMF_transform_dlight: case Shader::SMF_transform_dlight:
*scratch = *(LMatrix4f *)cache0; m = *(LMatrix4f *)cache0;
v = (*(LMatrix4f *)cache1).xform_vec(cache0[2].get_xyz()); v = (*(LMatrix4f *)cache1).xform_vec(cache0[2].get_xyz());
v.normalize(); v.normalize();
scratch->set_row(2, v); m.set_row(2, v);
v = (*(LMatrix4f *)cache1).xform_vec(cache0[3].get_xyz()); v = (*(LMatrix4f *)cache1).xform_vec(cache0[3].get_xyz());
v.normalize(); v.normalize();
scratch->set_row(3, v); m.set_row(3, v);
return (LVecBase4f *)scratch; return (LVecBase4f *)&m;
case Shader::SMF_transform_plight: case Shader::SMF_transform_plight:
{ {
// Careful not to touch the w component, which contains the near value. // 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()); LPoint3f point = (*(LMatrix4f *)cache1).xform_point(cache0[2].get_xyz());
(*scratch)(2, 0) = point[0]; m(2, 0) = point[0];
(*scratch)(2, 1) = point[1]; m(2, 1) = point[1];
(*scratch)(2, 2) = point[2]; m(2, 2) = point[2];
return (LVecBase4f *)scratch; return (LVecBase4f *)&m;
} }
case Shader::SMF_transform_slight: case Shader::SMF_transform_slight:
*scratch = *(LMatrix4f *)cache0; m = *(LMatrix4f *)cache0;
scratch->set_row(2, (*(LMatrix4f *)cache1).xform_point(cache0[2].get_xyz())); m.set_row(2, (*(LMatrix4f *)cache1).xform_point(cache0[2].get_xyz()));
v = (*(LMatrix4f *)cache1).xform_vec(cache0[3].get_xyz()); v = (*(LMatrix4f *)cache1).xform_vec(cache0[3].get_xyz());
v.normalize(); v.normalize();
scratch->set_row(3, v); m.set_row(3, v);
return (LVecBase4f *)scratch; return (LVecBase4f *)&m;
case Shader::SMF_shader_input_ptr:
return (const LVecBase4f *)fetch_ptr_parameter(spec, scratch);
} }
// Should never get here // Should never get here
*scratch = LMatrix4f::ident_mat(); m = LMatrix4f::ident_mat();
return (LVecBase4f *)scratch; 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;
} }
/** /**

View File

@ -337,7 +337,8 @@ public:
virtual void clear(DrawableRegion *clearable); virtual void clear(DrawableRegion *clearable);
void update_shader_matrix_cache(Shader *shader, LVecBase4f *cache, int altered); 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, void fetch_specified_part(Shader::ShaderMatInput input, InternalName *name,
LVecBase4f *into, int count = 1); LVecBase4f *into, int count = 1);
void fetch_specified_member(const NodePath &np, CPT_InternalName member, void fetch_specified_member(const NodePath &np, CPT_InternalName member,

View File

@ -190,48 +190,10 @@ void DXShaderContext9::
issue_parameters(GSG *gsg, int altered) { issue_parameters(GSG *gsg, int altered) {
#ifdef HAVE_CG #ifdef HAVE_CG
if (_cg_program) { 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) { if (altered & _shader->_mat_deps) {
if (altered & _shader->_mat_cache_deps) {
gsg->update_shader_matrix_cache(_shader, _mat_part_cache, altered); gsg->update_shader_matrix_cache(_shader, _mat_part_cache, altered);
}
LMatrix4f scratch; LMatrix4f scratch;

View File

@ -535,7 +535,7 @@ issue_parameters(int altered) {
// modified every frame and when we switch ShaderAttribs. // modified every frame and when we switch ShaderAttribs.
if (altered & (Shader::SSD_shaderinputs | Shader::SSD_frame)) { if (altered & (Shader::SSD_shaderinputs | Shader::SSD_frame)) {
// Iterate through _ptr parameters // 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::ShaderPtrSpec &spec = _shader->_ptr_spec[i];
const Shader::ShaderPtrData *ptr_data =_glgsg->fetch_ptr_parameter(spec); const Shader::ShaderPtrData *ptr_data =_glgsg->fetch_ptr_parameter(spec);
@ -690,11 +690,13 @@ issue_parameters(int altered) {
release_resources(); release_resources();
return; return;
} }
} }*/
} }
if (altered & _shader->_mat_deps) { if (altered & _shader->_mat_deps) {
if (altered & _shader->_mat_cache_deps) {
_glgsg->update_shader_matrix_cache(_shader, _mat_part_cache, altered); _glgsg->update_shader_matrix_cache(_shader, _mat_part_cache, altered);
}
LMatrix4f scratch; LMatrix4f scratch;
@ -709,13 +711,19 @@ issue_parameters(int altered) {
data += spec._offset; data += spec._offset;
CGparameter p = _cg_parameter_map[spec._id._seqno]; CGparameter p = _cg_parameter_map[spec._id._seqno];
if (spec._numeric_type == Shader::SPT_float) {
switch (spec._piece) { switch (spec._piece) {
case Shader::SMP_float: cgGLSetParameter1f(p, data[0]); continue; case Shader::SMP_scalar: cgGLSetParameter1f(p, data[0]); continue;
case Shader::SMP_vec2: cgGLSetParameter2fv(p, data); continue; case Shader::SMP_vec2: cgGLSetParameter2fv(p, data); continue;
case Shader::SMP_vec3: cgGLSetParameter3fv(p, data); continue; case Shader::SMP_vec3: cgGLSetParameter3fv(p, data); continue;
case Shader::SMP_vec4: cgGLSetParameter4fv(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_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_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_array: cgGLSetMatrixParameterArrayfc(p, 0, spec._array_count, data); continue;
case Shader::SMP_mat4_transpose: cgGLSetMatrixParameterfr(p, 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_column: cgGLSetParameter4f(p, data[0], data[4], data[ 8], data[12]); continue;
@ -731,10 +739,51 @@ issue_parameters(int altered) {
cgGLSetMatrixParameterfr(p, upper3.get_data()); cgGLSetMatrixParameterfr(p, upper3.get_data());
continue; continue;
} }
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; else if (spec._numeric_type == Shader::SPT_double) {
case Shader::SMP_ivec4: cgSetParameter4iv(p, (const int *)data); continue; 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);
}
} }
} }
} }

View File

@ -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. // We'll permit this too, simply because we can support it.
switch (param_type) { switch (param_type) {
case GL_FLOAT: case GL_FLOAT:
bind._piece = Shader::SMP_float; bind._piece = Shader::SMP_scalar;
break; break;
case GL_FLOAT_VEC2: case GL_FLOAT_VEC2:
bind._piece = Shader::SMP_vec2; bind._piece = Shader::SMP_vec2;
@ -404,7 +404,7 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
param_count = 0; param_count = 0;
_glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORMS, &param_count); _glgsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORMS, &param_count);
_shader->_ptr_spec.clear(); //_shader->_ptr_spec.clear();
_shader->_mat_spec.clear(); _shader->_mat_spec.clear();
_shader->_tex_spec.clear(); _shader->_tex_spec.clear();
for (int i = 0; i < param_count; ++i) { 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_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_VEC2:
case GL_BOOL_VEC3: case GL_BOOL_VEC3:
case GL_BOOL_VEC4: case GL_BOOL_VEC4:
bind._numeric_type = Shader::SPT_bool;
break;
case GL_UNSIGNED_INT: case GL_UNSIGNED_INT:
case GL_UNSIGNED_INT_VEC2: case GL_UNSIGNED_INT_VEC2:
case GL_UNSIGNED_INT_VEC3: case GL_UNSIGNED_INT_VEC3:
@ -1120,7 +1123,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
GLCAT.error() GLCAT.error()
<< "p3d_Material.shininess should be float\n"; << "p3d_Material.shininess should be float\n";
} }
bind._piece = Shader::SMP_float; bind._piece = Shader::SMP_scalar;
bind._offset = 15; bind._offset = 15;
_shader->cp_add_mat_spec(bind); _shader->cp_add_mat_spec(bind);
return; return;
@ -1131,7 +1134,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
<< "p3d_Material.roughness should be float\n"; << "p3d_Material.roughness should be float\n";
} }
bind._part[0] = Shader::SMO_attr_material2; bind._part[0] = Shader::SMO_attr_material2;
bind._piece = Shader::SMP_float; bind._piece = Shader::SMP_scalar;
bind._offset = 7; bind._offset = 7;
_shader->cp_add_mat_spec(bind); _shader->cp_add_mat_spec(bind);
return; return;
@ -1142,7 +1145,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
<< "p3d_Material.metallic should be bool or float\n"; << "p3d_Material.metallic should be bool or float\n";
} }
bind._part[0] = Shader::SMO_attr_material2; bind._part[0] = Shader::SMO_attr_material2;
bind._piece = Shader::SMP_float; bind._piece = Shader::SMP_scalar;
bind._offset = 4; bind._offset = 4;
_shader->cp_add_mat_spec(bind); _shader->cp_add_mat_spec(bind);
return; return;
@ -1153,7 +1156,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
<< "p3d_Material.refractiveIndex should be float\n"; << "p3d_Material.refractiveIndex should be float\n";
} }
bind._part[0] = Shader::SMO_attr_material2; bind._part[0] = Shader::SMO_attr_material2;
bind._piece = Shader::SMP_float; bind._piece = Shader::SMP_scalar;
bind._offset = 5; bind._offset = 5;
_shader->cp_add_mat_spec(bind); _shader->cp_add_mat_spec(bind);
return; return;
@ -1244,7 +1247,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._part[0] = Shader::SMO_attr_fog; bind._part[0] = Shader::SMO_attr_fog;
if (param_type == GL_FLOAT) { if (param_type == GL_FLOAT) {
bind._piece = Shader::SMP_float; bind._piece = Shader::SMP_scalar;
} else { } else {
GLCAT.error() GLCAT.error()
<< "p3d_Fog.density should be float\n"; << "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; bind._part[0] = Shader::SMO_attr_fog;
if (param_type == GL_FLOAT) { if (param_type == GL_FLOAT) {
bind._piece = Shader::SMP_float; bind._piece = Shader::SMP_scalar;
bind._offset = 1; bind._offset = 1;
} else { } else {
GLCAT.error() GLCAT.error()
@ -1267,7 +1270,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._part[0] = Shader::SMO_attr_fog; bind._part[0] = Shader::SMO_attr_fog;
if (param_type == GL_FLOAT) { if (param_type == GL_FLOAT) {
bind._piece = Shader::SMP_float; bind._piece = Shader::SMP_scalar;
bind._offset = 2; bind._offset = 2;
} else { } else {
GLCAT.error() GLCAT.error()
@ -1279,7 +1282,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._part[0] = Shader::SMO_attr_fog; bind._part[0] = Shader::SMO_attr_fog;
if (param_type == GL_FLOAT) { if (param_type == GL_FLOAT) {
bind._piece = Shader::SMP_float; bind._piece = Shader::SMP_scalar;
bind._offset = 3; bind._offset = 3;
} else { } else {
GLCAT.error() GLCAT.error()
@ -1354,7 +1357,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
switch (param_type) { switch (param_type) {
case GL_FLOAT: case GL_FLOAT:
bind._piece = Shader::SMP_float; bind._piece = Shader::SMP_scalar;
break; break;
case GL_FLOAT_VEC2: case GL_FLOAT_VEC2:
@ -1442,7 +1445,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
return; return;
} else if (noprefix == "FrameTime") { } else if (noprefix == "FrameTime") {
bind._piece = Shader::SMP_float; bind._piece = Shader::SMP_scalar;
bind._func = Shader::SMF_first; bind._func = Shader::SMF_first;
bind._part[0] = Shader::SMO_frame_time; bind._part[0] = Shader::SMO_frame_time;
bind._part[1] = Shader::SMO_identity; bind._part[1] = Shader::SMO_identity;
@ -1450,7 +1453,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
return; return;
} else if (noprefix == "DeltaFrameTime") { } else if (noprefix == "DeltaFrameTime") {
bind._piece = Shader::SMP_float; bind._piece = Shader::SMP_scalar;
bind._func = Shader::SMF_first; bind._func = Shader::SMF_first;
bind._part[0] = Shader::SMO_frame_delta; bind._part[0] = Shader::SMO_frame_delta;
bind._part[1] = Shader::SMO_identity; bind._part[1] = Shader::SMO_identity;
@ -1596,7 +1599,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._id = arg_id; bind._id = arg_id;
switch (param_type) { switch (param_type) {
case GL_FLOAT: case GL_FLOAT:
bind._piece = Shader::SMP_float; bind._piece = Shader::SMP_scalar;
break; break;
case GL_FLOAT_VEC2: case GL_FLOAT_VEC2:
bind._piece = Shader::SMP_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_VEC2:
case GL_UNSIGNED_INT_VEC3: case GL_UNSIGNED_INT_VEC3:
case GL_UNSIGNED_INT_VEC4: { case GL_UNSIGNED_INT_VEC4: {
Shader::ShaderPtrSpec bind; Shader::ShaderMatSpec bind;
bind._id = arg_id; bind._id = arg_id;
bind._func = Shader::SMF_shader_input_ptr;
switch (param_type) { switch (param_type) {
case GL_BOOL: case GL_BOOL:
case GL_INT: bind._piece = Shader::SMP_scalar;
case GL_UNSIGNED_INT: bind._numeric_type = Shader::SPT_bool;
case GL_FLOAT: bind._dim[1] = 1; break; bind._num_components = 1;
case GL_BOOL_VEC2: break;
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;
}
switch (param_type) {
case GL_BOOL:
case GL_BOOL_VEC2: case GL_BOOL_VEC2:
bind._piece = Shader::SMP_vec2;
bind._numeric_type = Shader::SPT_bool;
bind._num_components = 2;
break;
case GL_BOOL_VEC3: case GL_BOOL_VEC3:
bind._piece = Shader::SMP_vec3;
bind._numeric_type = Shader::SPT_bool;
bind._num_components = 3;
break;
case GL_BOOL_VEC4: case GL_BOOL_VEC4:
bind._piece = Shader::SMP_vec4;
bind._numeric_type = Shader::SPT_bool;
bind._num_components = 4;
break;
case GL_UNSIGNED_INT: 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: 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: 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: 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; break;
case GL_INT: case GL_INT:
bind._piece = Shader::SMP_scalar;
bind._numeric_type = Shader::SPT_int;
bind._num_components = 1;
break;
case GL_INT_VEC2: case GL_INT_VEC2:
bind._piece = Shader::SMP_vec2;
bind._numeric_type = Shader::SPT_int;
bind._num_components = 2;
break;
case GL_INT_VEC3: case GL_INT_VEC3:
bind._piece = Shader::SMP_vec3;
bind._numeric_type = Shader::SPT_int;
bind._num_components = 3;
break;
case GL_INT_VEC4: 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; break;
case GL_FLOAT: case GL_FLOAT:
bind._piece = Shader::SMP_scalar;
bind._numeric_type = Shader::SPT_float;
bind._num_components = 1;
break;
case GL_FLOAT_VEC2: case GL_FLOAT_VEC2:
bind._piece = Shader::SMP_vec2;
bind._numeric_type = Shader::SPT_float;
bind._num_components = 2;
break;
case GL_FLOAT_VEC3: case GL_FLOAT_VEC3:
bind._piece = Shader::SMP_vec3;
bind._numeric_type = Shader::SPT_float;
bind._num_components = 3;
break;
case GL_FLOAT_VEC4: case GL_FLOAT_VEC4:
bind._piece = Shader::SMP_vec4;
bind._numeric_type = Shader::SPT_float;
bind._num_components = 4;
break;
case GL_FLOAT_MAT3: 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: 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; break;
} }
bind._arg = InternalName::make(param_name); bind._part[0] = Shader::SMO_INVALID;
bind._dim[0] = 1; bind._part[1] = Shader::SMO_INVALID;
bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame; bind._arg[0] = InternalName::make(param_name);
bind._dep[1] = Shader::SSD_NONE; bind._arg[1] = nullptr;
_shader->_ptr_spec.push_back(bind); _shader->cp_add_mat_spec(bind);
return; return;
} }
case GL_IMAGE_2D: 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_VEC4:
case GL_FLOAT_MAT3: case GL_FLOAT_MAT3:
case GL_FLOAT_MAT4: { case GL_FLOAT_MAT4: {
Shader::ShaderPtrSpec bind; Shader::ShaderMatSpec bind;
bind._id = arg_id; bind._id = arg_id;
bind._func = Shader::SMF_shader_input_ptr;
switch (param_type) { switch (param_type) {
case GL_BOOL: case GL_BOOL:
case GL_INT: bind._piece = Shader::SMP_scalar_array;
case GL_FLOAT: bind._dim[1] = 1; break; bind._numeric_type = Shader::SPT_uint;
case GL_BOOL_VEC2: bind._num_components = 1;
case GL_INT_VEC2: break;
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;
}
switch (param_type) {
case GL_BOOL:
case GL_BOOL_VEC2: 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: 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: 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: 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: 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: 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: 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; break;
case GL_INT: case GL_INT:
bind._piece = Shader::SMP_scalar_array;
bind._numeric_type = Shader::SPT_int;
bind._num_components = 1;
break;
case GL_INT_VEC2: 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: 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: 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; break;
case GL_FLOAT: case GL_FLOAT:
bind._piece = Shader::SMP_scalar_array;
bind._numeric_type = Shader::SPT_float;
bind._num_components = 1;
break;
case GL_FLOAT_VEC2: 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: 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: 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: 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: 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; break;
} }
bind._arg = InternalName::make(param_name); bind._part[0] = Shader::SMO_INVALID;
bind._dim[0] = param_size; bind._part[1] = Shader::SMO_INVALID;
bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs | Shader::SSD_frame; bind._arg[0] = InternalName::make(param_name);
bind._dep[1] = Shader::SSD_NONE; bind._arg[1] = nullptr;
_shader->_ptr_spec.push_back(bind); bind._array_count = param_size;
_shader->cp_add_mat_spec(bind);
return; return;
} }
default: default:
@ -1967,6 +2069,7 @@ CLP(ShaderContext)::
~CLP(ShaderContext)() { ~CLP(ShaderContext)() {
// Don't call release_resources; we may not have an active context. // Don't call release_resources; we may not have an active context.
delete[] _mat_part_cache; delete[] _mat_part_cache;
delete[] _mat_scratch_space;
} }
/** /**
@ -2170,7 +2273,7 @@ issue_parameters(int altered) {
} }
// Iterate through _ptr parameters // 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::ShaderPtrSpec &spec = _shader->_ptr_spec[i];
Shader::ShaderPtrData ptr_data; Shader::ShaderPtrData ptr_data;
@ -2293,31 +2396,37 @@ issue_parameters(int altered) {
default: default:
continue; continue;
} }
} }*/
} }
if (altered & _shader->_mat_deps) { if (altered & _shader->_mat_deps) {
if (altered & _shader->_mat_cache_deps) {
_glgsg->update_shader_matrix_cache(_shader, _mat_part_cache, altered); _glgsg->update_shader_matrix_cache(_shader, _mat_part_cache, altered);
}
LMatrix4f scratch;
for (Shader::ShaderMatSpec &spec : _shader->_mat_spec) { for (Shader::ShaderMatSpec &spec : _shader->_mat_spec) {
if ((altered & spec._dep) == 0) { if ((altered & spec._dep) == 0) {
continue; 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; if (!val) continue;
const float *data = val->get_data(); const float *data = val->get_data();
data += spec._offset; data += spec._offset;
GLint p = spec._id._seqno; GLint p = spec._id._seqno;
if (spec._numeric_type == Shader::SPT_float) {
switch (spec._piece) { switch (spec._piece) {
case Shader::SMP_float: _glgsg->_glUniform1fv(p, 1, data); continue; case Shader::SMP_scalar: _glgsg->_glUniform1fv(p, 1, data); continue;
case Shader::SMP_vec2: _glgsg->_glUniform2fv(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_vec3: _glgsg->_glUniform3fv(p, 1, data); continue;
case Shader::SMP_vec4: _glgsg->_glUniform4fv(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_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_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_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_transpose: _glgsg->_glUniformMatrix4fv(p, 1, GL_TRUE, data); continue;
@ -2334,10 +2443,36 @@ issue_parameters(int altered) {
_glgsg->_glUniformMatrix3fv(p, 1, true, upper3.get_data()); _glgsg->_glUniformMatrix3fv(p, 1, true, upper3.get_data());
continue; continue;
} }
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; else if (spec._numeric_type == Shader::SPT_int) {
case Shader::SMP_ivec4: _glgsg->_glUniform4iv(p, 1, (int *)data); continue; 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);
}
}
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");
} }
} }
} }

View File

@ -113,6 +113,7 @@ private:
pvector<ImageInput> _glsl_img_inputs; pvector<ImageInput> _glsl_img_inputs;
LVecBase4f *_mat_part_cache = nullptr; LVecBase4f *_mat_part_cache = nullptr;
LVecBase4f *_mat_scratch_space = nullptr;
CLP(GraphicsStateGuardian) *_glgsg; CLP(GraphicsStateGuardian) *_glgsg;

View File

@ -602,6 +602,9 @@ cp_add_mat_spec(ShaderMatSpec &spec) {
int num_parts = (spec._func != SMF_first) ? 2 : 1; int num_parts = (spec._func != SMF_first) ? 2 : 1;
for (int p = 0; p < num_parts; ++p) { for (int p = 0; p < num_parts; ++p) {
if (spec._part[p] == SMO_INVALID) {
continue;
}
int dep = cp_dependency(spec._part[p]); int dep = cp_dependency(spec._part[p]);
spec._dep |= dep; spec._dep |= dep;
@ -724,10 +727,19 @@ cp_add_mat_spec(ShaderMatSpec &spec) {
assert(part._size == 4); assert(part._size == 4);
} }
_mat_cache_deps |= part._dep;
_mat_parts.push_back(std::move(part)); _mat_parts.push_back(std::move(part));
} }
spec._cache_offset[p] = offset + begin[p]; 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_spec.push_back(spec);
_mat_deps |= spec._dep; _mat_deps |= spec._dep;
@ -746,6 +758,15 @@ cp_get_mat_cache_size() const {
return size; 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 #ifdef HAVE_CG
/** /**
* *
@ -1483,7 +1504,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
if (!cp_errchk_parameter_float(p, 1, 1)) { if (!cp_errchk_parameter_float(p, 1, 1)) {
return false; return false;
} }
bind._piece = SMP_float; bind._piece = SMP_scalar;
bind._part[0] = SMO_frame_time; bind._part[0] = SMO_frame_time;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
@ -1635,25 +1656,25 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
case SAC_matrix: case SAC_matrix:
case SAC_scalar: case SAC_scalar:
case SAC_array: { case SAC_array: {
if (!cp_errchk_parameter_ptr(p)) if (!cp_errchk_parameter_ptr(p)) {
return false; return false;
}
ShaderPtrSpec bind; ShaderMatSpec bind;
bind._id = p._id; bind._id = p._id;
bind._arg = kinputname; bind._func = SMF_shader_input_ptr;
bind._info = p; bind._part[0] = SMO_INVALID;
bind._part[1] = SMO_INVALID;
// We specify SSD_frame because a PTA may be modified by the app from bind._arg[0] = kinputname;
// frame to frame, and we have no way to know. So, we must respecify a bind._arg[1] = nullptr;
// PTA at least once every frame. bind._array_count = arg_dim[0] * arg_dim[1];
bind._dep[0] = SSD_general | SSD_shaderinputs | SSD_frame; bind._num_components = arg_dim[2];
bind._dep[1] = SSD_NONE; bind._numeric_type = p._numeric_type;
bind._piece = (ShaderMatPiece)(SMP_scalar + (arg_dim[2] - 1));
memcpy(bind._dim,arg_dim,sizeof(int)*3);
// if dim[0] = -1, glShaderContext will not check the param size // if dim[0] = -1, glShaderContext will not check the param size
if (k_prefix) bind._dim[0] = -1; //if (k_prefix) bind._dim[0] = -1;
_ptr_spec.push_back(bind); cp_add_mat_spec(bind);
return true; return true;
} }
@ -2285,11 +2306,6 @@ cg_analyze_shader(const ShaderCaps &caps) {
_tex_spec[i]._id._seqno = seqno++; _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. // 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. // 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_mat = _mat_spec.size();
size_t n_tex = _tex_spec.size(); size_t n_tex = _tex_spec.size();
size_t n_var = _var_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 // This is a bit awkward, we have to go in and seperate out the combined
// program, since all the parameter bindings have changed. // program, since all the parameter bindings have changed.
@ -2513,19 +2528,6 @@ cg_compile_for(const ShaderCaps &caps, CGcontext context,
map[id._seqno] = p; 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. // Transfer ownership of the compiled shader.
if (_cg_vprogram != 0) { if (_cg_vprogram != 0) {
cgDestroyProgram(_cg_vprogram); cgDestroyProgram(_cg_vprogram);

View File

@ -292,21 +292,22 @@ public:
}; };
enum ShaderMatPiece { enum ShaderMatPiece {
SMP_float, SMP_scalar,
SMP_vec2, SMP_vec2,
SMP_vec3, SMP_vec3,
SMP_vec4, SMP_vec4,
SMP_scalar_array,
SMP_vec2_array,
SMP_vec3_array,
SMP_vec4_array, SMP_vec4_array,
SMP_mat3_whole,
SMP_mat3_array,
SMP_mat4_whole, SMP_mat4_whole,
SMP_mat4_array, SMP_mat4_array,
SMP_mat4_transpose, SMP_mat4_transpose,
SMP_mat4_column, SMP_mat4_column,
SMP_mat4_upper3x3, SMP_mat4_upper3x3,
SMP_mat4_transpose3x3, SMP_mat4_transpose3x3,
SMP_int,
SMP_ivec2,
SMP_ivec3,
SMP_ivec4,
}; };
enum ShaderStateDep { enum ShaderStateDep {
@ -339,6 +340,7 @@ public:
SMF_transform_dlight, SMF_transform_dlight,
SMF_transform_plight, SMF_transform_plight,
SMF_transform_slight, SMF_transform_slight,
SMF_shader_input_ptr,
}; };
struct ShaderArgId { struct ShaderArgId {
@ -352,6 +354,7 @@ public:
SPT_double, SPT_double,
SPT_int, SPT_int,
SPT_uint, SPT_uint,
SPT_bool,
SPT_unknown SPT_unknown
}; };
@ -443,6 +446,8 @@ public:
ShaderMatPiece _piece; ShaderMatPiece _piece;
int _offset = 0; int _offset = 0;
int _array_count = 1; int _array_count = 1;
int _num_components;
ShaderPtrType _numeric_type = SPT_float;
}; };
struct ShaderTexSpec { struct ShaderTexSpec {
@ -547,6 +552,7 @@ public:
int cp_dependency(ShaderMatInput inp); int cp_dependency(ShaderMatInput inp);
void cp_add_mat_spec(ShaderMatSpec &spec); void cp_add_mat_spec(ShaderMatSpec &spec);
size_t cp_get_mat_cache_size() const; size_t cp_get_mat_cache_size() const;
size_t cp_get_mat_scratch_size() const;
#ifdef HAVE_CG #ifdef HAVE_CG
void cg_recurse_parameters(CGparameter parameter, void cg_recurse_parameters(CGparameter parameter,
@ -606,13 +612,13 @@ public:
#endif #endif
public: public:
pvector<ShaderPtrSpec> _ptr_spec;
pvector<ShaderMatSpec> _mat_spec; pvector<ShaderMatSpec> _mat_spec;
pvector<ShaderTexSpec> _tex_spec; pvector<ShaderTexSpec> _tex_spec;
pvector<ShaderVarSpec> _var_spec; pvector<ShaderVarSpec> _var_spec;
pvector<ShaderMatPart> _mat_parts; pvector<ShaderMatPart> _mat_parts;
int _mat_cache_deps = 0;
int _mat_deps = 0; int _mat_deps = 0;
int _mat_cache_size = 0; int _mat_scratch_size = 4;
bool _error_flag; bool _error_flag;
ShaderFile _text; ShaderFile _text;

View File

@ -463,6 +463,26 @@ def test_glsl_pta_ivec4(gsg):
run_glsl_test(gsg, code, preamble, {'pta': pta}) 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): def test_glsl_pta_mat4(gsg):
pta = core.PTA_LMatrix4f(( pta = core.PTA_LMatrix4f((
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15),