shader: More efficient state-based shader input fetching

Previously every input was fetched as a matrix.  Now, every input is fetched as a vector, with matrices taking up multiple vectors.  This saves a lot of copying and a lot of space in the cache.

Furthermore, integer state-based inputs can be defined (for future use)

Naming still needs to be revised, since it's called the "mat part cache" etc.
This commit is contained in:
rdb 2023-09-17 15:56:36 +02:00
parent c99fe581d3
commit ba388e2866
11 changed files with 649 additions and 609 deletions

File diff suppressed because it is too large Load Diff

View File

@ -336,12 +336,12 @@ public:
virtual void clear(DrawableRegion *clearable); virtual void clear(DrawableRegion *clearable);
void update_shader_matrix_cache(Shader *shader, LMatrix4 *cache, int altered); void update_shader_matrix_cache(Shader *shader, LVecBase4f *cache, int altered);
const LMatrix4 *fetch_specified_value(Shader::ShaderMatSpec &spec, const LMatrix4 *cache, int altered); const LVecBase4f *fetch_specified_value(Shader::ShaderMatSpec &spec, const LVecBase4f *cache, int altered);
void fetch_specified_part(Shader::ShaderMatInput input, InternalName *name, void fetch_specified_part(Shader::ShaderMatInput input, InternalName *name,
LMatrix4 *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,
LMatrix4 &t); LVecBase4f &v);
PT(Texture) fetch_specified_texture(Shader::ShaderTexSpec &spec, PT(Texture) fetch_specified_texture(Shader::ShaderTexSpec &spec,
SamplerState &sampler, int &view); SamplerState &sampler, int &view);
const Shader::ShaderPtrData *fetch_ptr_parameter(const Shader::ShaderPtrSpec& spec); const Shader::ShaderPtrData *fetch_ptr_parameter(const Shader::ShaderPtrSpec& spec);

View File

@ -75,7 +75,7 @@ DXShaderContext9(Shader *s, GSG *gsg) : ShaderContext(s) {
} }
#endif #endif
_mat_part_cache = new LMatrix4[s->cp_get_mat_cache_size()]; _mat_part_cache = new LVecBase4f[s->cp_get_mat_cache_size()];
} }
/** /**
@ -184,14 +184,6 @@ unbind(GSG *gsg) {
* the parameters were issued, no part of the render state has changed except * the parameters were issued, no part of the render state has changed except
* the external and internal transforms. * the external and internal transforms.
*/ */
#if DEBUG_SHADER
PN_stdfloat *global_data = 0;
ShaderContext::ShaderMatSpec *global_shader_mat_spec = 0;
InternalName *global_internal_name_0 = 0;
InternalName *global_internal_name_1 = 0;
#endif
void DXShaderContext9:: void DXShaderContext9::
issue_parameters(GSG *gsg, int altered) { issue_parameters(GSG *gsg, int altered) {
#ifdef HAVE_CG #ifdef HAVE_CG
@ -249,106 +241,42 @@ issue_parameters(GSG *gsg, int altered) {
continue; continue;
} }
const LMatrix4 *val = gsg->fetch_specified_value(spec, _mat_part_cache, altered); const LVecBase4f *val = gsg->fetch_specified_value(spec, _mat_part_cache, altered);
if (val) { if (val) {
HRESULT hr; const float *data = (const float *)val + spec._offset;
PN_stdfloat v [4]; LVecBase4f v;
LMatrix4f temp_matrix = LCAST(float, *val); LMatrix4f temp_matrix;
LMatrix3f temp_matrix3; LMatrix3f temp_matrix3;
hr = D3D_OK;
const float *data;
data = temp_matrix.get_data();
#if DEBUG_SHADER
// DEBUG
global_data = (PN_stdfloat *)data;
global_shader_mat_spec = &spec;
global_internal_name_0 = global_shader_mat_spec->_arg[0];
global_internal_name_1 = global_shader_mat_spec->_arg[1];
#endif
switch (spec._piece) { switch (spec._piece) {
case Shader::SMP_whole: case Shader::SMP_mat4_whole:
// TRANSPOSE REQUIRED // TRANSPOSE REQUIRED
temp_matrix.transpose_in_place(); temp_matrix.transpose_from(*(const LMatrix4f *)data);
data = temp_matrix.get_data(); data = temp_matrix.get_data();
hr = cgD3D9SetUniform(p, data);
break; break;
case Shader::SMP_transpose: case Shader::SMP_mat4_column:
// NO TRANSPOSE REQUIRED v.set(data[0], data[4], data[8], data[12]);
hr = cgD3D9SetUniform(p, data); data = v.get_data();
break; break;
case Shader::SMP_row0: case Shader::SMP_mat4_upper3x3:
hr = cgD3D9SetUniform(p, data + 0);
break;
case Shader::SMP_row1:
hr = cgD3D9SetUniform(p, data + 4);
break;
case Shader::SMP_row2:
hr = cgD3D9SetUniform(p, data + 8);
break;
case Shader::SMP_row3x1:
case Shader::SMP_row3x2:
case Shader::SMP_row3x3:
case Shader::SMP_row3:
hr = cgD3D9SetUniform(p, data + 12);
break;
case Shader::SMP_col0:
v[0] = data[0]; v[1] = data[4]; v[2] = data[8]; v[3] = data[12];
hr = cgD3D9SetUniform(p, v);
break;
case Shader::SMP_col1:
v[0] = data[1]; v[1] = data[5]; v[2] = data[9]; v[3] = data[13];
hr = cgD3D9SetUniform(p, v);
break;
case Shader::SMP_col2:
v[0] = data[2]; v[1] = data[6]; v[2] = data[10]; v[3] = data[14];
hr = cgD3D9SetUniform(p, v);
break;
case Shader::SMP_col3:
v[0] = data[3]; v[1] = data[7]; v[2] = data[11]; v[3] = data[15];
hr = cgD3D9SetUniform(p, v);
break;
case Shader::SMP_upper3x3:
// TRANSPOSE REQUIRED // TRANSPOSE REQUIRED
temp_matrix3 = temp_matrix.get_upper_3(); temp_matrix3.set(data[0], data[4], data[8], data[1], data[5], data[9], data[2], data[6], data[10]);
temp_matrix3.transpose_in_place();
data = temp_matrix3.get_data(); data = temp_matrix3.get_data();
hr = cgD3D9SetUniform(p, data);
break; break;
case Shader::SMP_transpose3x3: case Shader::SMP_mat4_transpose3x3:
// NO TRANSPOSE REQUIRED // NO TRANSPOSE REQUIRED
temp_matrix3 = temp_matrix.get_upper_3(); temp_matrix3.set(data[0], data[1], data[2], data[4], data[5], data[6], data[8], data[9], data[10]);
data = temp_matrix3.get_data(); data = temp_matrix3.get_data();
hr = cgD3D9SetUniform(p, data);
break; break;
case Shader::SMP_cell15:
hr = cgD3D9SetUniform(p, data + 15);
continue;
case Shader::SMP_cell14:
hr = cgD3D9SetUniform(p, data + 14);
continue;
case Shader::SMP_cell13:
hr = cgD3D9SetUniform(p, data + 13);
continue;
default: default:
dxgsg9_cat.error()
<< "issue_parameters () SMP parameter type not implemented " << spec._piece << "\n";
break; break;
} }
HRESULT hr = cgD3D9SetUniform(p, data);
if (FAILED(hr)) { if (FAILED(hr)) {
std::string name = "unnamed"; std::string name = "unnamed";

View File

@ -87,7 +87,7 @@ private:
pvector <CGparameter> _cg_parameter_map; pvector <CGparameter> _cg_parameter_map;
#endif #endif
LMatrix4 *_mat_part_cache = nullptr; LVecBase4f *_mat_part_cache = nullptr;
private: private:
void release_resources(void); void release_resources(void);

View File

@ -329,7 +329,7 @@ CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderConte
} }
} }
_mat_part_cache = new LMatrix4[_shader->cp_get_mat_cache_size()]; _mat_part_cache = new LVecBase4f[_shader->cp_get_mat_cache_size()];
_glgsg->report_my_gl_errors(); _glgsg->report_my_gl_errors();
} }
@ -699,46 +699,36 @@ issue_parameters(int altered) {
continue; continue;
} }
const LMatrix4 *val = _glgsg->fetch_specified_value(spec, _mat_part_cache, altered); const LVecBase4f *val = _glgsg->fetch_specified_value(spec, _mat_part_cache, altered);
if (!val) continue; if (!val) continue;
const PN_stdfloat *data = val->get_data(); const float *data = val->get_data();
data += spec._offset;
CGparameter p = _cg_parameter_map[spec._id._seqno]; CGparameter p = _cg_parameter_map[spec._id._seqno];
switch (spec._piece) { switch (spec._piece) {
case Shader::SMP_whole: GLfc(cgGLSetMatrixParameter)(p, data); continue; case Shader::SMP_float: cgGLSetParameter1f(p, data[0]); continue;
case Shader::SMP_transpose: GLfr(cgGLSetMatrixParameter)(p, data); continue; case Shader::SMP_vec2: cgGLSetParameter2fv(p, data); continue;
case Shader::SMP_col0: GLf(cgGLSetParameter4)(p, data[0], data[4], data[ 8], data[12]); continue; case Shader::SMP_vec3: cgGLSetParameter3fv(p, data); continue;
case Shader::SMP_col1: GLf(cgGLSetParameter4)(p, data[1], data[5], data[ 9], data[13]); continue; case Shader::SMP_vec4: cgGLSetParameter4fv(p, data); continue;
case Shader::SMP_col2: GLf(cgGLSetParameter4)(p, data[2], data[6], data[10], data[14]); continue; case Shader::SMP_mat4_whole: cgGLSetMatrixParameterfc(p, data); continue;
case Shader::SMP_col3: GLf(cgGLSetParameter4)(p, data[3], data[7], data[11], data[15]); continue; case Shader::SMP_mat4_transpose: cgGLSetMatrixParameterfr(p, data); continue;
case Shader::SMP_row0: GLfv(cgGLSetParameter4)(p, data+ 0); continue; case Shader::SMP_mat4_column: cgGLSetParameter4f(p, data[0], data[4], data[ 8], data[12]); continue;
case Shader::SMP_row1: GLfv(cgGLSetParameter4)(p, data+ 4); continue; case Shader::SMP_mat4_upper3x3:
case Shader::SMP_row2: GLfv(cgGLSetParameter4)(p, data+ 8); continue;
case Shader::SMP_row3: GLfv(cgGLSetParameter4)(p, data+12); continue;
case Shader::SMP_row3x1: GLfv(cgGLSetParameter1)(p, data+12); continue;
case Shader::SMP_row3x2: GLfv(cgGLSetParameter2)(p, data+12); continue;
case Shader::SMP_row3x3: GLfv(cgGLSetParameter3)(p, data+12); continue;
case Shader::SMP_upper3x3:
{ {
LMatrix3 upper3 = val->get_upper_3(); LMatrix3f upper3(data[0], data[1], data[2], data[4], data[5], data[6], data[8], data[9], data[10]);
GLfc(cgGLSetMatrixParameter)(p, upper3.get_data()); cgGLSetMatrixParameterfc(p, upper3.get_data());
continue; continue;
} }
case Shader::SMP_transpose3x3: case Shader::SMP_mat4_transpose3x3:
{ {
LMatrix3 upper3 = val->get_upper_3(); LMatrix3f upper3(data[0], data[1], data[2], data[4], data[5], data[6], data[8], data[9], data[10]);
GLfr(cgGLSetMatrixParameter)(p, upper3.get_data()); cgGLSetMatrixParameterfr(p, upper3.get_data());
continue; continue;
} }
case Shader::SMP_cell15: case Shader::SMP_int: cgSetParameter1i(p, ((const int *)data)[0]); continue;
GLf(cgGLSetParameter1)(p, data[15]); case Shader::SMP_ivec2: cgSetParameter2iv(p, (const int *)data); continue;
continue; case Shader::SMP_ivec3: cgSetParameter3iv(p, (const int *)data); continue;
case Shader::SMP_cell14: case Shader::SMP_ivec4: cgSetParameter4iv(p, (const int *)data); continue;
GLf(cgGLSetParameter1)(p, data[14]);
continue;
case Shader::SMP_cell13:
GLf(cgGLSetParameter1)(p, data[13]);
continue;
} }
} }
} }

View File

@ -75,7 +75,7 @@ private:
long _transform_table_size; long _transform_table_size;
long _slider_table_size; long _slider_table_size;
LMatrix4 *_mat_part_cache = nullptr; LVecBase4f *_mat_part_cache = nullptr;
pvector<CGparameter> _cg_parameter_map; pvector<CGparameter> _cg_parameter_map;
WCPT(RenderState) _state_rs; WCPT(RenderState) _state_rs;

View File

@ -152,30 +152,54 @@ parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, GLenum param_t
// Decide whether this is a matrix or vector. // Decide whether this is a matrix or vector.
if (param_type == GL_FLOAT_MAT4) { if (param_type == GL_FLOAT_MAT4) {
if (pieces[0] == "trans") bind._piece = Shader::SMP_whole; if (pieces[0] == "trans") bind._piece = Shader::SMP_mat4_whole;
else if (pieces[0] == "tpose") bind._piece = Shader::SMP_transpose; else if (pieces[0] == "tpose") bind._piece = Shader::SMP_mat4_transpose;
else { else {
GLCAT.error() << basename << " should be vec4, not mat3\n"; GLCAT.error() << basename << " should be vec4, not mat3\n";
return false; return false;
} }
} else if (param_type == GL_FLOAT_MAT3) { } else if (param_type == GL_FLOAT_MAT3) {
if (pieces[0] == "trans") bind._piece = Shader::SMP_upper3x3; if (pieces[0] == "trans") bind._piece = Shader::SMP_mat4_upper3x3;
else if (pieces[0] == "tpose") bind._piece = Shader::SMP_transpose3x3; else if (pieces[0] == "tpose") bind._piece = Shader::SMP_mat4_transpose3x3;
else { else {
GLCAT.error() << basename << " should be vec4, not mat3\n"; GLCAT.error() << basename << " should be vec4, not mat3\n";
return false; return false;
} }
} else if (param_type == GL_FLOAT_VEC4) { } else if (param_type == GL_FLOAT_VEC4) {
if (pieces[0] == "trans") bind._piece = Shader::SMP_col0; if (pieces[0] == "trans") bind._piece = Shader::SMP_mat4_column;
else if (pieces[0] == "tpose") bind._piece = Shader::SMP_row0; else if (pieces[0] == "tpose") bind._piece = Shader::SMP_vec4;
else if (pieces[0] == "row0") bind._piece = Shader::SMP_row0; else if (pieces[0] == "row0") {
else if (pieces[0] == "row1") bind._piece = Shader::SMP_row1; bind._piece = Shader::SMP_vec4;
else if (pieces[0] == "row2") bind._piece = Shader::SMP_row2; bind._offset = 0;
else if (pieces[0] == "row3") bind._piece = Shader::SMP_row3; }
else if (pieces[0] == "col0") bind._piece = Shader::SMP_col0; else if (pieces[0] == "row1") {
else if (pieces[0] == "col1") bind._piece = Shader::SMP_col1; bind._piece = Shader::SMP_vec4;
else if (pieces[0] == "col2") bind._piece = Shader::SMP_col2; bind._offset = 4;
else if (pieces[0] == "col3") bind._piece = Shader::SMP_col3; }
else if (pieces[0] == "row2") {
bind._piece = Shader::SMP_vec4;
bind._offset = 8;
}
else if (pieces[0] == "row3") {
bind._piece = Shader::SMP_vec4;
bind._offset = 12;
}
else if (pieces[0] == "col0") {
bind._piece = Shader::SMP_mat4_column;
bind._offset = 0;
}
else if (pieces[0] == "col1") {
bind._piece = Shader::SMP_mat4_column;
bind._offset = 1;
}
else if (pieces[0] == "col2") {
bind._piece = Shader::SMP_mat4_column;
bind._offset = 2;
}
else if (pieces[0] == "col3") {
bind._piece = Shader::SMP_mat4_column;
bind._offset = 3;
}
else { else {
GLCAT.error() << basename << " should be mat4, not vec4\n"; GLCAT.error() << basename << " should be mat4, not vec4\n";
return false; return false;
@ -184,13 +208,13 @@ 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_row3x1; bind._piece = Shader::SMP_float;
break; break;
case GL_FLOAT_VEC2: case GL_FLOAT_VEC2:
bind._piece = Shader::SMP_row3x2; bind._piece = Shader::SMP_vec2;
break; break;
case GL_FLOAT_VEC3: case GL_FLOAT_VEC3:
bind._piece = Shader::SMP_row3x3; bind._piece = Shader::SMP_vec3;
break; break;
default: default:
GLCAT.error() << basename << " should be vec4\n"; GLCAT.error() << basename << " should be vec4\n";
@ -234,7 +258,7 @@ parse_and_set_short_hand_shader_vars(Shader::ShaderArgId &arg_id, GLenum param_t
if (param_size > 1) { if (param_size > 1) {
// We support arrays of rows and arrays of columns, so we can run the // We support arrays of rows and arrays of columns, so we can run the
// GLSL shaders that cgc spits out. // GLSL shaders that cgc spits out.
if (bind._piece == Shader::SMP_row0 || bind._piece == Shader::SMP_col0) { if (bind._piece == Shader::SMP_vec4 || bind._piece == Shader::SMP_mat4_column) {
if (param_size > 4) { if (param_size > 4) {
GLCAT.warning() << basename << "[" << param_size << "] is too large, only the first four elements will be defined\n"; GLCAT.warning() << basename << "[" << param_size << "] is too large, only the first four elements will be defined\n";
param_size = 4; param_size = 4;
@ -396,7 +420,7 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
_glgsg->_current_shader_context->bind(); _glgsg->_current_shader_context->bind();
} }
_mat_part_cache = new LMatrix4[_shader->cp_get_mat_cache_size()]; _mat_part_cache = new LVecBase4f[_shader->cp_get_mat_cache_size()];
} }
/** /**
@ -827,15 +851,15 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._func = Shader::SMF_compose; bind._func = Shader::SMF_compose;
if (param_type == GL_FLOAT_MAT3) { if (param_type == GL_FLOAT_MAT3) {
if (transpose) { if (transpose) {
bind._piece = Shader::SMP_upper3x3; bind._piece = Shader::SMP_mat4_upper3x3;
} else { } else {
bind._piece = Shader::SMP_transpose3x3; bind._piece = Shader::SMP_mat4_transpose3x3;
} }
} else if (param_type == GL_FLOAT_MAT4) { } else if (param_type == GL_FLOAT_MAT4) {
if (transpose) { if (transpose) {
bind._piece = Shader::SMP_transpose; bind._piece = Shader::SMP_mat4_transpose;
} else { } else {
bind._piece = Shader::SMP_whole; bind._piece = Shader::SMP_mat4_whole;
} }
} else { } else {
GLCAT.error() GLCAT.error()
@ -941,13 +965,15 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
// A matrix member of a p3d_LightSource struct. // A matrix member of a p3d_LightSource struct.
if (strncmp(name_buffer, "shadowViewMatrix", 127) == 0) { if (strncmp(name_buffer, "shadowViewMatrix", 127) == 0) {
if (inverse) { if (inverse) {
// Tack inverse back onto the end. GLCAT.error()
strcpy(name_buffer + strlen(name_buffer), "Inverse"); << "p3d_LightSource struct does not provide a matrix named "
<< name_buffer << "Inverse!\n";
return;
} }
bind._func = Shader::SMF_first; bind._func = Shader::SMF_first;
bind._part[0] = Shader::SMO_light_source_i_attrib; bind._part[0] = Shader::SMO_apiview_to_apiclip_light_source_i;
bind._arg[0] = InternalName::make(name_buffer); bind._arg[0] = nullptr;
bind._part[1] = Shader::SMO_identity; bind._part[1] = Shader::SMO_identity;
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
@ -957,8 +983,8 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._func = Shader::SMF_compose; bind._func = Shader::SMF_compose;
bind._part[0] = Shader::SMO_model_to_apiview; bind._part[0] = Shader::SMO_model_to_apiview;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
bind._part[1] = Shader::SMO_light_source_i_attrib; bind._part[1] = Shader::SMO_apiview_to_apiclip_light_source_i;
bind._arg[1] = InternalName::make("shadowViewMatrix"); bind._arg[1] = nullptr;
static bool warned = false; static bool warned = false;
if (!warned) { if (!warned) {
@ -1061,7 +1087,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
<< "p3d_Material.baseColor should be vec4\n"; << "p3d_Material.baseColor should be vec4\n";
} }
bind._part[0] = Shader::SMO_attr_material2; bind._part[0] = Shader::SMO_attr_material2;
bind._piece = Shader::SMP_row0; bind._piece = Shader::SMP_vec4;
_shader->cp_add_mat_spec(bind); _shader->cp_add_mat_spec(bind);
return; return;
@ -1070,7 +1096,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
GLCAT.error() GLCAT.error()
<< "p3d_Material.ambient should be vec4\n"; << "p3d_Material.ambient should be vec4\n";
} }
bind._piece = Shader::SMP_row0; bind._piece = Shader::SMP_vec4;
_shader->cp_add_mat_spec(bind); _shader->cp_add_mat_spec(bind);
return; return;
@ -1079,7 +1105,8 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
GLCAT.error() GLCAT.error()
<< "p3d_Material.diffuse should be vec4\n"; << "p3d_Material.diffuse should be vec4\n";
} }
bind._piece = Shader::SMP_row1; bind._piece = Shader::SMP_vec4;
bind._offset = 4;
_shader->cp_add_mat_spec(bind); _shader->cp_add_mat_spec(bind);
return; return;
@ -1088,7 +1115,8 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
GLCAT.error() GLCAT.error()
<< "p3d_Material.emission should be vec4\n"; << "p3d_Material.emission should be vec4\n";
} }
bind._piece = Shader::SMP_row2; bind._piece = Shader::SMP_vec4;
bind._offset = 8;
_shader->cp_add_mat_spec(bind); _shader->cp_add_mat_spec(bind);
return; return;
@ -1097,7 +1125,8 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
GLCAT.error() GLCAT.error()
<< "p3d_Material.specular should be vec3\n"; << "p3d_Material.specular should be vec3\n";
} }
bind._piece = Shader::SMP_row3x3; bind._piece = Shader::SMP_vec3;
bind._offset = 12;
_shader->cp_add_mat_spec(bind); _shader->cp_add_mat_spec(bind);
return; return;
@ -1106,7 +1135,8 @@ 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_cell15; bind._piece = Shader::SMP_float;
bind._offset = 15;
_shader->cp_add_mat_spec(bind); _shader->cp_add_mat_spec(bind);
return; return;
@ -1116,7 +1146,8 @@ 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_cell15; bind._piece = Shader::SMP_float;
bind._offset = 7;
_shader->cp_add_mat_spec(bind); _shader->cp_add_mat_spec(bind);
return; return;
@ -1126,7 +1157,8 @@ 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_row3x1; bind._piece = Shader::SMP_float;
bind._offset = 4;
_shader->cp_add_mat_spec(bind); _shader->cp_add_mat_spec(bind);
return; return;
@ -1136,7 +1168,8 @@ 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_cell13; bind._piece = Shader::SMP_float;
bind._offset = 5;
_shader->cp_add_mat_spec(bind); _shader->cp_add_mat_spec(bind);
return; return;
} }
@ -1151,9 +1184,9 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
if (param_type == GL_FLOAT_VEC3) { if (param_type == GL_FLOAT_VEC3) {
bind._piece = Shader::SMP_row3x3; bind._piece = Shader::SMP_vec3;
} else if (param_type == GL_FLOAT_VEC4) { } else if (param_type == GL_FLOAT_VEC4) {
bind._piece = Shader::SMP_row3; bind._piece = Shader::SMP_vec4;
} else { } else {
GLCAT.error() GLCAT.error()
<< "p3d_ColorScale should be vec3 or vec4\n"; << "p3d_ColorScale should be vec3 or vec4\n";
@ -1172,9 +1205,9 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
if (param_type == GL_FLOAT_VEC3) { if (param_type == GL_FLOAT_VEC3) {
bind._piece = Shader::SMP_row3x3; bind._piece = Shader::SMP_vec3;
} else if (param_type == GL_FLOAT_VEC4) { } else if (param_type == GL_FLOAT_VEC4) {
bind._piece = Shader::SMP_row3; bind._piece = Shader::SMP_vec3;
} else { } else {
GLCAT.error() GLCAT.error()
<< "p3d_Color should be vec3 or vec4\n"; << "p3d_Color should be vec3 or vec4\n";
@ -1193,7 +1226,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
Shader::ShaderMatSpec bind; Shader::ShaderMatSpec bind;
bind._id = arg_id; bind._id = arg_id;
bind._id._seqno = p + i; bind._id._seqno = p + i;
bind._piece = Shader::SMP_row3; bind._piece = Shader::SMP_vec4;
bind._func = Shader::SMF_first; bind._func = Shader::SMF_first;
bind._index = i; bind._index = i;
bind._part[0] = Shader::SMO_apiview_clipplane_i; bind._part[0] = Shader::SMO_apiview_clipplane_i;
@ -1216,9 +1249,9 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._part[0] = Shader::SMO_attr_fogcolor; bind._part[0] = Shader::SMO_attr_fogcolor;
if (param_type == GL_FLOAT_VEC3) { if (param_type == GL_FLOAT_VEC3) {
bind._piece = Shader::SMP_row3x3; bind._piece = Shader::SMP_vec4;
} else if (param_type == GL_FLOAT_VEC4) { } else if (param_type == GL_FLOAT_VEC4) {
bind._piece = Shader::SMP_row3; bind._piece = Shader::SMP_vec4;
} else { } else {
GLCAT.error() GLCAT.error()
<< "p3d_Fog.color should be vec3 or vec4\n"; << "p3d_Fog.color should be vec3 or vec4\n";
@ -1229,7 +1262,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_row3x1; bind._piece = Shader::SMP_float;
} else { } else {
GLCAT.error() GLCAT.error()
<< "p3d_Fog.density should be float\n"; << "p3d_Fog.density should be float\n";
@ -1240,7 +1273,8 @@ 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_cell13; bind._piece = Shader::SMP_float;
bind._offset = 13;
} else { } else {
GLCAT.error() GLCAT.error()
<< "p3d_Fog.start should be float\n"; << "p3d_Fog.start should be float\n";
@ -1251,7 +1285,8 @@ 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_cell14; bind._piece = Shader::SMP_float;
bind._offset = 14;
} else { } else {
GLCAT.error() GLCAT.error()
<< "p3d_Fog.end should be float\n"; << "p3d_Fog.end should be float\n";
@ -1262,7 +1297,8 @@ 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_cell15; bind._piece = Shader::SMP_float;
bind._offset = 15;
} else { } else {
GLCAT.error() GLCAT.error()
<< "p3d_Fog.scale should be float\n"; << "p3d_Fog.scale should be float\n";
@ -1283,9 +1319,9 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
if (param_type == GL_FLOAT_VEC3) { if (param_type == GL_FLOAT_VEC3) {
bind._piece = Shader::SMP_row3x3; bind._piece = Shader::SMP_vec3;
} else if (param_type == GL_FLOAT_VEC4) { } else if (param_type == GL_FLOAT_VEC4) {
bind._piece = Shader::SMP_row3; bind._piece = Shader::SMP_vec4;
} else { } else {
GLCAT.error() GLCAT.error()
<< "p3d_LightModel.ambient should be vec3 or vec4\n"; << "p3d_LightModel.ambient should be vec3 or vec4\n";
@ -1329,26 +1365,26 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._id = arg_id; bind._id = arg_id;
bind._func = Shader::SMF_first; bind._func = Shader::SMF_first;
bind._index = index; bind._index = index;
bind._part[0] = Shader::SMO_light_source_i_attrib; bind._part[0] = Shader::SMO_light_source_i_vec_attrib;
bind._arg[0] = InternalName::make(member_name); bind._arg[0] = InternalName::make(member_name);
bind._part[1] = Shader::SMO_identity; bind._part[1] = Shader::SMO_identity;
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
switch (param_type) { switch (param_type) {
case GL_FLOAT: case GL_FLOAT:
bind._piece = Shader::SMP_row3x1; bind._piece = Shader::SMP_float;
break; break;
case GL_FLOAT_VEC2: case GL_FLOAT_VEC2:
bind._piece = Shader::SMP_row3x2; bind._piece = Shader::SMP_vec2;
break; break;
case GL_FLOAT_VEC3: case GL_FLOAT_VEC3:
bind._piece = Shader::SMP_row3x3; bind._piece = Shader::SMP_vec3;
break; break;
case GL_FLOAT_VEC4: case GL_FLOAT_VEC4:
bind._piece = Shader::SMP_row3; bind._piece = Shader::SMP_vec4;
break; break;
default: default:
@ -1390,7 +1426,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
bind._part[1] = Shader::SMO_identity; bind._part[1] = Shader::SMO_identity;
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
bind._piece = Shader::SMP_row3; bind._piece = Shader::SMP_vec4;
_shader->cp_add_mat_spec(bind); _shader->cp_add_mat_spec(bind);
return; return;
} }
@ -1408,7 +1444,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
if (noprefix == "ViewMatrix") { if (noprefix == "ViewMatrix") {
bind._piece = Shader::SMP_whole; bind._piece = Shader::SMP_mat4_whole;
bind._func = Shader::SMF_compose; bind._func = Shader::SMF_compose;
bind._part[0] = Shader::SMO_world_to_view; bind._part[0] = Shader::SMO_world_to_view;
bind._part[1] = Shader::SMO_view_to_apiview; bind._part[1] = Shader::SMO_view_to_apiview;
@ -1416,7 +1452,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
return; return;
} else if (noprefix == "InverseViewMatrix" || noprefix == "ViewMatrixInverse") { } else if (noprefix == "InverseViewMatrix" || noprefix == "ViewMatrixInverse") {
bind._piece = Shader::SMP_whole; bind._piece = Shader::SMP_mat4_whole;
bind._func = Shader::SMF_compose; bind._func = Shader::SMF_compose;
bind._part[0] = Shader::SMO_apiview_to_view; bind._part[0] = Shader::SMO_apiview_to_view;
bind._part[1] = Shader::SMO_view_to_world; bind._part[1] = Shader::SMO_view_to_world;
@ -1424,7 +1460,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_row3x1; bind._piece = Shader::SMP_float;
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;
@ -1432,7 +1468,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_row3x1; bind._piece = Shader::SMP_float;
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;
@ -1516,7 +1552,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
case GL_FLOAT_MAT3: { case GL_FLOAT_MAT3: {
Shader::ShaderMatSpec bind; Shader::ShaderMatSpec bind;
bind._id = arg_id; bind._id = arg_id;
bind._piece = Shader::SMP_upper3x3; bind._piece = Shader::SMP_mat4_upper3x3;
bind._func = Shader::SMF_first; bind._func = Shader::SMF_first;
bind._part[0] = Shader::SMO_mat_constant_x; bind._part[0] = Shader::SMO_mat_constant_x;
bind._arg[0] = InternalName::make(param_name); bind._arg[0] = InternalName::make(param_name);
@ -1528,7 +1564,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
case GL_FLOAT_MAT4: { case GL_FLOAT_MAT4: {
Shader::ShaderMatSpec bind; Shader::ShaderMatSpec bind;
bind._id = arg_id; bind._id = arg_id;
bind._piece = Shader::SMP_whole; bind._piece = Shader::SMP_mat4_whole;
bind._func = Shader::SMF_first; bind._func = Shader::SMF_first;
bind._part[1] = Shader::SMO_identity; bind._part[1] = Shader::SMO_identity;
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
@ -1552,8 +1588,8 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._func = Shader::SMF_compose; bind._func = Shader::SMF_compose;
bind._part[0] = Shader::SMO_model_to_apiview; bind._part[0] = Shader::SMO_model_to_apiview;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
bind._part[1] = Shader::SMO_mat_constant_x_attrib; bind._part[1] = Shader::SMO_apiview_to_apiclip_light_source_i;
bind._arg[1] = iname->get_parent()->append("shadowViewMatrix"); bind._arg[1] = nullptr;
} else { } else {
bind._part[0] = Shader::SMO_mat_constant_x_attrib; bind._part[0] = Shader::SMO_mat_constant_x_attrib;
bind._arg[0] = InternalName::make(param_name); bind._arg[0] = InternalName::make(param_name);
@ -1578,16 +1614,16 @@ 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_row3x1; bind._piece = Shader::SMP_float;
break; break;
case GL_FLOAT_VEC2: case GL_FLOAT_VEC2:
bind._piece = Shader::SMP_row3x2; bind._piece = Shader::SMP_vec2;
break; break;
case GL_FLOAT_VEC3: case GL_FLOAT_VEC3:
bind._piece = Shader::SMP_row3x3; bind._piece = Shader::SMP_vec3;
break; break;
default: default:
bind._piece = Shader::SMP_row3; bind._piece = Shader::SMP_vec4;
} }
bind._func = Shader::SMF_first; bind._func = Shader::SMF_first;
bind._part[0] = Shader::SMO_vec_constant_x_attrib; bind._part[0] = Shader::SMO_vec_constant_x_attrib;
@ -2263,61 +2299,36 @@ issue_parameters(int altered) {
continue; continue;
} }
const LMatrix4 *val = _glgsg->fetch_specified_value(spec, _mat_part_cache, altered); const LVecBase4f *val = _glgsg->fetch_specified_value(spec, _mat_part_cache, altered);
if (!val) continue; if (!val) continue;
#ifndef STDFLOAT_DOUBLE const float *data = val->get_data();
// In this case, the data is already single-precision. data += spec._offset;
const PN_float32 *data = val->get_data();
#else
// In this case, we have to convert it.
LMatrix4f valf = LCAST(PN_float32, *val);
const PN_float32 *data = valf.get_data();
#endif
GLint p = spec._id._seqno; GLint p = spec._id._seqno;
switch (spec._piece) { switch (spec._piece) {
case Shader::SMP_whole: _glgsg->_glUniformMatrix4fv(p, 1, GL_FALSE, data); continue; case Shader::SMP_float: _glgsg->_glUniform1fv(p, 1, data); continue;
case Shader::SMP_transpose: _glgsg->_glUniformMatrix4fv(p, 1, GL_TRUE, data); continue; case Shader::SMP_vec2: _glgsg->_glUniform2fv(p, 1, data); continue;
case Shader::SMP_col0: _glgsg->_glUniform4f(p, data[0], data[4], data[ 8], data[12]); continue; case Shader::SMP_vec3: _glgsg->_glUniform3fv(p, 1, data); continue;
case Shader::SMP_col1: _glgsg->_glUniform4f(p, data[1], data[5], data[ 9], data[13]); continue; case Shader::SMP_vec4: _glgsg->_glUniform4fv(p, 1, data); continue;
case Shader::SMP_col2: _glgsg->_glUniform4f(p, data[2], data[6], data[10], data[14]); continue; case Shader::SMP_mat4_whole: _glgsg->_glUniformMatrix4fv(p, 1, GL_FALSE, data); continue;
case Shader::SMP_col3: _glgsg->_glUniform4f(p, data[3], data[7], data[11], data[15]); continue; case Shader::SMP_mat4_transpose: _glgsg->_glUniformMatrix4fv(p, 1, GL_TRUE, data); continue;
case Shader::SMP_row0: _glgsg->_glUniform4fv(p, 1, data+ 0); continue; case Shader::SMP_mat4_column: _glgsg->_glUniform4f(p, data[0], data[4], data[8], data[12]); continue;
case Shader::SMP_row1: _glgsg->_glUniform4fv(p, 1, data+ 4); continue; case Shader::SMP_mat4_upper3x3:
case Shader::SMP_row2: _glgsg->_glUniform4fv(p, 1, data+ 8); continue;
case Shader::SMP_row3: _glgsg->_glUniform4fv(p, 1, data+12); continue;
case Shader::SMP_row3x1: _glgsg->_glUniform1fv(p, 1, data+12); continue;
case Shader::SMP_row3x2: _glgsg->_glUniform2fv(p, 1, data+12); continue;
case Shader::SMP_row3x3: _glgsg->_glUniform3fv(p, 1, data+12); continue;
case Shader::SMP_upper3x3:
{ {
#ifndef STDFLOAT_DOUBLE LMatrix3f upper3(data[0], data[1], data[2], data[4], data[5], data[6], data[8], data[9], data[10]);
LMatrix3f upper3 = val->get_upper_3();
#else
LMatrix3f upper3 = valf.get_upper_3();
#endif
_glgsg->_glUniformMatrix3fv(p, 1, false, upper3.get_data()); _glgsg->_glUniformMatrix3fv(p, 1, false, upper3.get_data());
continue; continue;
} }
case Shader::SMP_transpose3x3: case Shader::SMP_mat4_transpose3x3:
{ {
#ifndef STDFLOAT_DOUBLE LMatrix3f upper3(data[0], data[1], data[2], data[4], data[5], data[6], data[8], data[9], data[10]);
LMatrix3f upper3 = val->get_upper_3();
#else
LMatrix3f upper3 = valf.get_upper_3();
#endif
_glgsg->_glUniformMatrix3fv(p, 1, true, upper3.get_data()); _glgsg->_glUniformMatrix3fv(p, 1, true, upper3.get_data());
continue; continue;
} }
case Shader::SMP_cell15: case Shader::SMP_int: _glgsg->_glUniform1i(p, ((int *)data)[0]);
_glgsg->_glUniform1fv(p, 1, data+15); case Shader::SMP_ivec2: _glgsg->_glUniform2iv(p, 1, (int *)data);
continue; case Shader::SMP_ivec3: _glgsg->_glUniform3iv(p, 1, (int *)data);
case Shader::SMP_cell14: case Shader::SMP_ivec4: _glgsg->_glUniform4iv(p, 1, (int *)data);
_glgsg->_glUniform1fv(p, 1, data+14);
continue;
case Shader::SMP_cell13:
_glgsg->_glUniform1fv(p, 1, data+13);
continue;
} }
} }
} }

View File

@ -112,7 +112,7 @@ private:
}; };
pvector<ImageInput> _glsl_img_inputs; pvector<ImageInput> _glsl_img_inputs;
LMatrix4 *_mat_part_cache = nullptr; LVecBase4f *_mat_part_cache = nullptr;
CLP(GraphicsStateGuardian) *_glgsg; CLP(GraphicsStateGuardian) *_glgsg;

View File

@ -24,16 +24,8 @@
#ifndef STDFLOAT_DOUBLE #ifndef STDFLOAT_DOUBLE
#define GLf(name) name ## f #define GLf(name) name ## f
#define GLfv(name) name ## fv
#define GLfc(name) name ## fc
#define GLfr(name) name ## fr
#define GLf_str "f"
#else // STDFLOAT_DOUBLE #else // STDFLOAT_DOUBLE
#define GLf(name) name ## d #define GLf(name) name ## d
#define GLfv(name) name ## dv
#define GLfc(name) name ## dc
#define GLfr(name) name ## dr
#define GLf_str "d"
#endif // STDFLOAT_DOUBLE #endif // STDFLOAT_DOUBLE
#endif // GLf #endif // GLf

View File

@ -459,11 +459,13 @@ cp_dependency(ShaderMatInput inp) {
} }
} }
if ((inp == SMO_light_ambient) || if ((inp == SMO_light_ambient) ||
(inp == SMO_light_source_i_attrib) || (inp == SMO_light_source_i_vec_attrib) ||
(inp == SMO_apiview_to_apiclip_light_source_i) ||
(inp == SMO_light_source_i_packed)) { (inp == SMO_light_source_i_packed)) {
dep |= SSD_light | SSD_frame; dep |= SSD_light | SSD_frame;
} }
if (inp == SMO_light_source_i_attrib || if (inp == SMO_light_source_i_vec_attrib ||
inp == SMO_apiview_to_apiclip_light_source_i ||
inp == SMO_light_source_i_packed || inp == SMO_light_source_i_packed ||
inp == SMO_mat_constant_x_attrib || inp == SMO_mat_constant_x_attrib ||
inp == SMO_vec_constant_x_attrib) { inp == SMO_vec_constant_x_attrib) {
@ -579,14 +581,13 @@ cp_add_mat_spec(ShaderMatSpec &spec) {
for (int i = 0; i < 2; ++i) { for (int i = 0; i < 2; ++i) {
if (spec._part[i] == SMO_texmat_i || if (spec._part[i] == SMO_texmat_i ||
spec._part[i] == SMO_inv_texmat_i || spec._part[i] == SMO_inv_texmat_i ||
spec._part[i] == SMO_light_source_i_attrib || spec._part[i] == SMO_light_source_i_vec_attrib ||
spec._part[i] == SMO_apiview_to_apiclip_light_source_i ||
spec._part[i] == SMO_light_product_i_ambient || spec._part[i] == SMO_light_product_i_ambient ||
spec._part[i] == SMO_light_product_i_diffuse || spec._part[i] == SMO_light_product_i_diffuse ||
spec._part[i] == SMO_light_product_i_specular || spec._part[i] == SMO_light_product_i_specular ||
spec._part[i] == SMO_apiview_clipplane_i || spec._part[i] == SMO_apiview_clipplane_i ||
spec._part[i] == SMO_tex_is_alpha_i || spec._part[i] == SMO_tex_is_alpha_i ||
spec._part[i] == SMO_transform_i ||
spec._part[i] == SMO_slider_i ||
spec._part[i] == SMO_light_source_i_packed || spec._part[i] == SMO_light_source_i_packed ||
spec._part[i] == SMO_texscale_i || spec._part[i] == SMO_texscale_i ||
spec._part[i] == SMO_texcolor_i) { spec._part[i] == SMO_texcolor_i) {
@ -610,6 +611,9 @@ cp_add_mat_spec(ShaderMatSpec &spec) {
for (i = 0; i < _mat_parts.size(); ++i) { for (i = 0; i < _mat_parts.size(); ++i) {
ShaderMatPart &part = _mat_parts[i]; ShaderMatPart &part = _mat_parts[i];
if (part._part == spec._part[p] && part._arg == spec._arg[p]) { if (part._part == spec._part[p] && part._arg == spec._arg[p]) {
if (spec._func != SMF_first) {
assert(part._size == 4);
}
int diff = end[p] - part._count; int diff = end[p] - part._count;
if (diff <= 0) { if (diff <= 0) {
// The existing cache entry is big enough. // The existing cache entry is big enough.
@ -618,18 +622,18 @@ cp_add_mat_spec(ShaderMatSpec &spec) {
// It's not big enough. Enlarge it, which means we have to change the // It's not big enough. Enlarge it, which means we have to change the
// offset of some of the other spec entries. // offset of some of the other spec entries.
for (ShaderMatSpec &spec : _mat_spec) { for (ShaderMatSpec &spec : _mat_spec) {
if (spec._cache_offset[0] >= offset + part._count) { if (spec._cache_offset[0] >= offset + part._size * part._count) {
spec._cache_offset[0] += diff; spec._cache_offset[0] += diff * part._size;
} }
if (spec._cache_offset[1] >= offset + part._count) { if (spec._cache_offset[1] >= offset + part._size * part._count) {
spec._cache_offset[1] += diff; spec._cache_offset[1] += diff * part._size;
} }
} }
part._count = end[p]; part._count = end[p];
break; break;
} }
} }
offset += part._count; offset += part._count * part._size;
} }
if (i == _mat_parts.size()) { if (i == _mat_parts.size()) {
// Didn't find this part yet, create a new one. // Didn't find this part yet, create a new one.
@ -638,6 +642,88 @@ cp_add_mat_spec(ShaderMatSpec &spec) {
part._count = end[p]; part._count = end[p];
part._arg = spec._arg[p]; part._arg = spec._arg[p];
part._dep = dep; part._dep = dep;
switch (part._part) {
case SMO_INVALID:
part._size = 0;
break;
case SMO_window_size:
case SMO_pixel_size:
case SMO_texpad_x:
case SMO_texpix_x:
case SMO_attr_material:
case SMO_attr_color:
case SMO_attr_colorscale:
case SMO_satten_x:
case SMO_plane_x:
case SMO_clipplane_x:
case SMO_vec_constant_x:
case SMO_attr_fog:
case SMO_attr_fogcolor:
case SMO_frame_number:
case SMO_frame_time:
case SMO_frame_delta:
case SMO_vec_constant_x_attrib:
case SMO_light_ambient:
case SMO_light_source_i_vec_attrib:
case SMO_light_product_i_ambient:
case SMO_light_product_i_diffuse:
case SMO_light_product_i_specular:
case SMO_apiview_clipplane_i:
case SMO_tex_is_alpha_i:
case SMO_texscale_i:
case SMO_texcolor_i:
case SMO_texconst_i:
case SMO_attr_pointparams:
part._size = 1;
break;
case SMO_attr_material2:
part._size = 2;
break;
case SMO_identity:
case SMO_alight_x:
case SMO_dlight_x:
case SMO_plight_x:
case SMO_slight_x:
case SMO_texmat_i:
case SMO_mat_constant_x:
case SMO_world_to_view:
case SMO_view_to_world:
case SMO_model_to_view:
case SMO_view_to_model:
case SMO_apiview_to_view:
case SMO_view_to_apiview:
case SMO_clip_to_view:
case SMO_view_to_clip:
case SMO_apiclip_to_view:
case SMO_view_to_apiclip:
case SMO_view_x_to_view:
case SMO_view_to_view_x:
case SMO_apiview_x_to_view:
case SMO_view_to_apiview_x:
case SMO_clip_x_to_view:
case SMO_view_to_clip_x:
case SMO_apiclip_x_to_view:
case SMO_view_to_apiclip_x:
case SMO_mat_constant_x_attrib:
case SMO_apiview_to_apiclip_light_source_i:
case SMO_model_to_apiview:
case SMO_apiview_to_model:
case SMO_apiview_to_apiclip:
case SMO_apiclip_to_apiview:
case SMO_inv_texmat_i:
case SMO_light_source_i_packed:
part._size = 4;
break;
}
if (spec._func != SMF_first) {
assert(part._size == 4);
}
_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];
@ -648,13 +734,14 @@ cp_add_mat_spec(ShaderMatSpec &spec) {
} }
/** /**
* Returns the total size of the matrix part cache. * Returns the total size of the matrix part cache in terms of number of
* vectors.
*/ */
size_t Shader:: size_t Shader::
cp_get_mat_cache_size() const { cp_get_mat_cache_size() const {
size_t size = 0; size_t size = 0;
for (const ShaderMatPart &part : _mat_parts) { for (const ShaderMatPart &part : _mat_parts) {
size += part._count; size += part._size * part._count;
} }
return size; return size;
} }
@ -858,12 +945,12 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
} }
ShaderMatSpec bind; ShaderMatSpec bind;
bind._id = p._id; bind._id = p._id;
bind._piece = SMP_whole; bind._piece = SMP_mat4_whole;
bind._func = SMF_compose; bind._func = SMF_compose;
bind._part[1] = SMO_light_source_i_attrib;
bind._arg[1] = InternalName::make("shadowViewMatrix");
bind._part[0] = SMO_view_to_apiview; bind._part[0] = SMO_view_to_apiview;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
bind._part[1] = SMO_apiview_to_apiclip_light_source_i;
bind._arg[1] = nullptr;
bind._index = atoi(pieces[2].c_str()); bind._index = atoi(pieces[2].c_str());
cp_add_mat_spec(bind); cp_add_mat_spec(bind);
@ -969,42 +1056,46 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
ShaderMatSpec bind; ShaderMatSpec bind;
bind._id = p._id; bind._id = p._id;
bind._piece = SMP_whole; bind._piece = SMP_mat4_whole;
bind._func = SMF_compose; bind._func = SMF_compose;
bind._part[1] = SMO_light_source_i_attrib;
bind._arg[1] = InternalName::make("shadowViewMatrix");
bind._part[0] = SMO_view_to_apiview; bind._part[0] = SMO_view_to_apiview;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
bind._part[1] = SMO_apiview_to_apiclip_light_source_i;
bind._arg[1] = nullptr;
bind._index = atoi(pieces[2].c_str()); bind._index = atoi(pieces[2].c_str());
int next = 1; int next = 1;
pieces.push_back(""); pieces.push_back("");
// Decide whether this is a matrix or vector. // Decide whether this is a matrix or vector.
if (pieces[0]=="trans") bind._piece = SMP_whole; if (pieces[0][0] == 't') { // trans or tpose
else if (pieces[0]=="tpose") bind._piece = SMP_transpose; bool tpose = (pieces[0][1] == 'p');
else if (pieces[0]=="row0") bind._piece = SMP_row0;
else if (pieces[0]=="row1") bind._piece = SMP_row1;
else if (pieces[0]=="row2") bind._piece = SMP_row2;
else if (pieces[0]=="row3") bind._piece = SMP_row3;
else if (pieces[0]=="col0") bind._piece = SMP_col0;
else if (pieces[0]=="col1") bind._piece = SMP_col1;
else if (pieces[0]=="col2") bind._piece = SMP_col2;
else if (pieces[0]=="col3") bind._piece = SMP_col3;
if ((bind._piece == SMP_whole)||(bind._piece == SMP_transpose)) {
if (p._type == SAT_mat3x3) { if (p._type == SAT_mat3x3) {
if (!cp_errchk_parameter_float(p, 9, 9)) return false; if (!cp_errchk_parameter_float(p, 9, 9)) {
return false;
if (bind._piece == SMP_transpose) {
bind._piece = SMP_transpose3x3;
} else {
bind._piece = SMP_upper3x3;
} }
} else if (!cp_errchk_parameter_float(p, 16, 16)) { bind._piece = tpose ? SMP_mat4_transpose3x3 : SMP_mat4_upper3x3;
}
else {
if (!cp_errchk_parameter_float(p, 16, 16)) {
return false;
}
bind._piece = tpose ? SMP_mat4_transpose : SMP_mat4_whole;
}
}
else if (pieces[0][0] == 'r') { // row0, row1, row2, row3
if (!cp_errchk_parameter_float(p, 4, 4)) {
return false; return false;
} }
} else { bind._piece = SMP_vec4;
if (!cp_errchk_parameter_float(p, 4, 4)) return false; bind._offset = (pieces[0][3] - '0') * 4;
}
else if (pieces[0][0] == 'c') { // col0, col1, col2, col3
if (!cp_errchk_parameter_float(p, 4, 4)) {
return false;
}
bind._piece = SMP_mat4_column;
bind._offset = pieces[0][3] - '0';
} }
if (!cp_parse_coord_sys(p, pieces, next, bind, true)) { if (!cp_parse_coord_sys(p, pieces, next, bind, true)) {
@ -1037,7 +1128,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
return false; return false;
} }
bind._id = p._id; bind._id = p._id;
bind._piece = SMP_transpose; bind._piece = SMP_mat4_transpose;
bind._func = SMF_first; bind._func = SMF_first;
bind._part[0] = SMO_attr_material; bind._part[0] = SMO_attr_material;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
@ -1048,7 +1139,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
return false; return false;
} }
bind._id = p._id; bind._id = p._id;
bind._piece = SMP_row3; bind._piece = SMP_vec4;
bind._func = SMF_first; bind._func = SMF_first;
bind._part[0] = SMO_attr_color; bind._part[0] = SMO_attr_color;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
@ -1059,7 +1150,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
return false; return false;
} }
bind._id = p._id; bind._id = p._id;
bind._piece = SMP_row3; bind._piece = SMP_vec4;
bind._func = SMF_first; bind._func = SMF_first;
bind._part[0] = SMO_attr_colorscale; bind._part[0] = SMO_attr_colorscale;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
@ -1070,7 +1161,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
return false; return false;
} }
bind._id = p._id; bind._id = p._id;
bind._piece = SMP_row3; bind._piece = SMP_vec4;
bind._func = SMF_first; bind._func = SMF_first;
bind._part[0] = SMO_attr_fog; bind._part[0] = SMO_attr_fog;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
@ -1081,7 +1172,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
return false; return false;
} }
bind._id = p._id; bind._id = p._id;
bind._piece = SMP_row3; bind._piece = SMP_vec4;
bind._func = SMF_first; bind._func = SMF_first;
bind._part[0] = SMO_attr_fogcolor; bind._part[0] = SMO_attr_fogcolor;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
@ -1092,7 +1183,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
return false; return false;
} }
bind._id = p._id; bind._id = p._id;
bind._piece = SMP_row3; bind._piece = SMP_vec4;
bind._func = SMF_first; bind._func = SMF_first;
bind._part[0] = SMO_light_ambient; bind._part[0] = SMO_light_ambient;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
@ -1103,7 +1194,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
return false; return false;
} }
bind._id = p._id; bind._id = p._id;
bind._piece = SMP_transpose; bind._piece = SMP_mat4_transpose;
bind._func = SMF_first; bind._func = SMF_first;
bind._part[0] = SMO_light_source_i_packed; bind._part[0] = SMO_light_source_i_packed;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
@ -1115,9 +1206,9 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
return false; return false;
} }
bind._id = p._id; bind._id = p._id;
bind._piece = SMP_row3; bind._piece = SMP_vec4;
bind._func = SMF_first; bind._func = SMF_first;
bind._part[0] = SMO_light_source_i_attrib; bind._part[0] = SMO_light_source_i_vec_attrib;
bind._arg[0] = InternalName::make("specular"); bind._arg[0] = InternalName::make("specular");
bind._part[1] = SMO_identity; bind._part[1] = SMO_identity;
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
@ -1127,7 +1218,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
return false; return false;
} }
bind._id = p._id; bind._id = p._id;
bind._piece = SMP_row3; bind._piece = SMP_vec4;
bind._func = SMF_first; bind._func = SMF_first;
bind._part[0] = SMO_attr_pointparams; bind._part[0] = SMO_attr_pointparams;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
@ -1165,7 +1256,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
} }
ShaderMatSpec bind; ShaderMatSpec bind;
bind._id = p._id; bind._id = p._id;
bind._piece = SMP_row3; bind._piece = SMP_vec4;
bind._func = SMF_first; bind._func = SMF_first;
bind._part[0] = SMO_alight_x; bind._part[0] = SMO_alight_x;
bind._arg[0] = InternalName::make(pieces[1]); bind._arg[0] = InternalName::make(pieces[1]);
@ -1185,7 +1276,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
} }
ShaderMatSpec bind; ShaderMatSpec bind;
bind._id = p._id; bind._id = p._id;
bind._piece = SMP_row3; bind._piece = SMP_vec4;
bind._func = SMF_first; bind._func = SMF_first;
bind._part[0] = SMO_satten_x; bind._part[0] = SMO_satten_x;
bind._arg[0] = InternalName::make(pieces[1]); bind._arg[0] = InternalName::make(pieces[1]);
@ -1204,7 +1295,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
} }
ShaderMatSpec bind; ShaderMatSpec bind;
bind._id = p._id; bind._id = p._id;
bind._piece = SMP_transpose; bind._piece = SMP_mat4_transpose;
int next = 1; int next = 1;
pieces.push_back(""); pieces.push_back("");
if (pieces[next] == "") { if (pieces[next] == "") {
@ -1245,7 +1336,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
} }
ShaderMatSpec bind; ShaderMatSpec bind;
bind._id = p._id; bind._id = p._id;
bind._piece = SMP_whole; bind._piece = SMP_mat4_whole;
bind._func = SMF_first; bind._func = SMF_first;
bind._part[0] = SMO_texmat_i; bind._part[0] = SMO_texmat_i;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
@ -1266,7 +1357,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
} }
ShaderMatSpec bind; ShaderMatSpec bind;
bind._id = p._id; bind._id = p._id;
bind._piece = SMP_row3; bind._piece = SMP_vec4;
bind._func = SMF_first; bind._func = SMF_first;
bind._part[0] = SMO_texscale_i; bind._part[0] = SMO_texscale_i;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
@ -1287,7 +1378,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
} }
ShaderMatSpec bind; ShaderMatSpec bind;
bind._id = p._id; bind._id = p._id;
bind._piece = SMP_row3; bind._piece = SMP_vec4;
bind._func = SMF_first; bind._func = SMF_first;
bind._part[0] = SMO_texcolor_i; bind._part[0] = SMO_texcolor_i;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
@ -1308,7 +1399,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
} }
ShaderMatSpec bind; ShaderMatSpec bind;
bind._id = p._id; bind._id = p._id;
bind._piece = SMP_row3; bind._piece = SMP_vec4;
bind._func = SMF_first; bind._func = SMF_first;
bind._part[0] = SMO_texconst_i; bind._part[0] = SMO_texconst_i;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
@ -1329,7 +1420,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
} }
ShaderMatSpec bind; ShaderMatSpec bind;
bind._id = p._id; bind._id = p._id;
bind._piece = SMP_row3; bind._piece = SMP_vec4;
bind._func = SMF_first; bind._func = SMF_first;
bind._part[0] = SMO_plane_x; bind._part[0] = SMO_plane_x;
bind._arg[0] = InternalName::make(pieces[1]); bind._arg[0] = InternalName::make(pieces[1]);
@ -1349,7 +1440,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
} }
ShaderMatSpec bind; ShaderMatSpec bind;
bind._id = p._id; bind._id = p._id;
bind._piece = SMP_row3; bind._piece = SMP_vec4;
bind._func = SMF_first; bind._func = SMF_first;
bind._part[0] = SMO_clipplane_x; bind._part[0] = SMO_clipplane_x;
bind._arg[0] = InternalName::make(pieces[1]); bind._arg[0] = InternalName::make(pieces[1]);
@ -1370,7 +1461,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
} }
ShaderMatSpec bind; ShaderMatSpec bind;
bind._id = p._id; bind._id = p._id;
bind._piece = SMP_row3; bind._piece = SMP_vec4;
bind._func = SMF_first; bind._func = SMF_first;
bind._part[1] = SMO_identity; bind._part[1] = SMO_identity;
bind._arg[1] = nullptr; bind._arg[1] = nullptr;
@ -1392,7 +1483,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_row3x1; bind._piece = SMP_float;
bind._part[0] = SMO_frame_time; bind._part[0] = SMO_frame_time;
bind._arg[0] = nullptr; bind._arg[0] = nullptr;
@ -1479,7 +1570,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
} }
ShaderMatSpec bind; ShaderMatSpec bind;
bind._id = p._id; bind._id = p._id;
bind._piece = SMP_row3; bind._piece = SMP_vec4;
bind._func = SMF_first; bind._func = SMF_first;
bind._part[0] = SMO_texpad_x; bind._part[0] = SMO_texpad_x;
bind._arg[0] = InternalName::make(pieces[1]); bind._arg[0] = InternalName::make(pieces[1]);
@ -1498,7 +1589,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
} }
ShaderMatSpec bind; ShaderMatSpec bind;
bind._id = p._id; bind._id = p._id;
bind._piece = SMP_row3; bind._piece = SMP_vec4;
bind._func = SMF_first; bind._func = SMF_first;
bind._part[0] = SMO_texpix_x; bind._part[0] = SMO_texpix_x;
bind._arg[0] = InternalName::make(pieces[1]); bind._arg[0] = InternalName::make(pieces[1]);

View File

@ -183,7 +183,8 @@ public:
SMO_vec_constant_x_attrib, SMO_vec_constant_x_attrib,
SMO_light_ambient, SMO_light_ambient,
SMO_light_source_i_attrib, SMO_light_source_i_vec_attrib,
SMO_apiview_to_apiclip_light_source_i,
SMO_light_product_i_ambient, SMO_light_product_i_ambient,
SMO_light_product_i_diffuse, SMO_light_product_i_diffuse,
@ -205,9 +206,6 @@ public:
// Hack for text rendering. Don't use in user shaders. // Hack for text rendering. Don't use in user shaders.
SMO_tex_is_alpha_i, SMO_tex_is_alpha_i,
SMO_transform_i,
SMO_slider_i,
SMO_light_source_i_packed, SMO_light_source_i_packed,
// Texture scale component of texture matrix. // Texture scale component of texture matrix.
@ -294,24 +292,19 @@ public:
}; };
enum ShaderMatPiece { enum ShaderMatPiece {
SMP_whole, SMP_float,
SMP_transpose, SMP_vec2,
SMP_row0, SMP_vec3,
SMP_row1, SMP_vec4,
SMP_row2, SMP_mat4_whole,
SMP_row3, SMP_mat4_transpose,
SMP_col0, SMP_mat4_column,
SMP_col1, SMP_mat4_upper3x3,
SMP_col2, SMP_mat4_transpose3x3,
SMP_col3, SMP_int,
SMP_row3x1, SMP_ivec2,
SMP_row3x2, SMP_ivec3,
SMP_row3x3, SMP_ivec4,
SMP_upper3x3,
SMP_transpose3x3,
SMP_cell15,
SMP_cell14,
SMP_cell13,
}; };
enum ShaderStateDep { enum ShaderStateDep {
@ -339,11 +332,11 @@ public:
}; };
enum ShaderMatFunc { enum ShaderMatFunc {
SMF_first,
SMF_compose, SMF_compose,
SMF_transform_dlight, SMF_transform_dlight,
SMF_transform_plight, SMF_transform_plight,
SMF_transform_slight, SMF_transform_slight,
SMF_first,
}; };
struct ShaderArgId { struct ShaderArgId {
@ -422,12 +415,14 @@ public:
/** /**
* Describes a matrix making up a single part of the ShaderMatInput cache. * Describes a matrix making up a single part of the ShaderMatInput cache.
* The cache is made up of a continuous array of matrices, as described by * The cache is made up of a continuous array of vectors, as described by
* a successive list of ShaderMatPart (each of which takes up _count matrices) * a successive list of ShaderMatPart (each of which takes up _count times
* _size vectors)
*/ */
struct ShaderMatPart { struct ShaderMatPart {
ShaderMatInput _part; ShaderMatInput _part;
PT(InternalName) _arg; PT(InternalName) _arg;
int _size = 1;
int _count = 1; int _count = 1;
int _dep = SSD_NONE; int _dep = SSD_NONE;
}; };
@ -441,10 +436,11 @@ public:
ShaderMatFunc _func; ShaderMatFunc _func;
ShaderMatInput _part[2]; ShaderMatInput _part[2];
PT(InternalName) _arg[2]; PT(InternalName) _arg[2];
LMatrix4 _value; LMatrix4f _value;
int _dep = SSD_NONE; int _dep = SSD_NONE;
int _index = 0; int _index = 0;
ShaderMatPiece _piece; ShaderMatPiece _piece;
int _offset = 0;
}; };
struct ShaderTexSpec { struct ShaderTexSpec {