shader: support double-precision vertex columns in GLSL

This commit is contained in:
rdb 2018-07-26 13:50:54 +02:00
parent 7fe72c47f3
commit ecfeae8a27
4 changed files with 86 additions and 43 deletions

View File

@ -885,17 +885,21 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) {
_glgsg->enable_vertex_attrib_array(p);
if (bind._integer) {
_glgsg->_glVertexAttribIPointer(p, num_values, type,
stride, client_pointer);
} else if (numeric_type == GeomEnums::NT_packed_dabc) {
if (numeric_type == GeomEnums::NT_packed_dabc) {
// GL_BGRA is a special accepted value available since OpenGL 3.2.
// It requires us to pass GL_TRUE for normalized.
_glgsg->_glVertexAttribPointer(p, GL_BGRA, GL_UNSIGNED_BYTE,
GL_TRUE, stride, client_pointer);
} else {
} else if (bind._numeric_type == Shader::SPT_float ||
numeric_type == GeomEnums::NT_float32) {
_glgsg->_glVertexAttribPointer(p, num_values, type,
normalized, stride, client_pointer);
} else if (bind._numeric_type == Shader::SPT_double) {
_glgsg->_glVertexAttribLPointer(p, num_values, type,
stride, client_pointer);
} else {
_glgsg->_glVertexAttribIPointer(p, num_values, type,
stride, client_pointer);
}
if (divisor > 0) {
@ -952,10 +956,12 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) {
// So, we work around this by just binding something silly to 0.
// This breaks flat colors, but it's better than invisible objects?
_glgsg->enable_vertex_attrib_array(0);
if (bind._integer) {
_glgsg->_glVertexAttribIPointer(0, 4, GL_INT, 0, 0);
} else {
if (bind._numeric_type == Shader::SPT_float) {
_glgsg->_glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0);
} else if (bind._numeric_type == Shader::SPT_double) {
_glgsg->_glVertexAttribLPointer(0, 4, GL_DOUBLE, 0, 0);
} else {
_glgsg->_glVertexAttribIPointer(0, 4, GL_INT, 0, 0);
}
} else if (p >= 0) {

View File

@ -426,18 +426,34 @@ reflect_attribute(int i, char *name_buffer, GLsizei name_buflen) {
bind._elements = 1;
// Check if this is an integer input- if so, we have to bind it differently.
bind._integer = (param_type == GL_BOOL ||
param_type == GL_BOOL_VEC2 ||
param_type == GL_BOOL_VEC3 ||
param_type == GL_BOOL_VEC4 ||
param_type == GL_INT ||
param_type == GL_INT_VEC2 ||
param_type == GL_INT_VEC3 ||
param_type == GL_INT_VEC4 ||
param_type == GL_UNSIGNED_INT_VEC2 ||
param_type == GL_UNSIGNED_INT_VEC3 ||
param_type == GL_UNSIGNED_INT_VEC4 ||
param_type == GL_UNSIGNED_INT);
switch (param_type) {
case GL_INT:
case GL_INT_VEC2:
case GL_INT_VEC3:
case GL_INT_VEC4:
bind._numeric_type = Shader::SPT_int;
break;
case GL_BOOL:
case GL_BOOL_VEC2:
case GL_BOOL_VEC3:
case GL_BOOL_VEC4:
case GL_UNSIGNED_INT:
case GL_UNSIGNED_INT_VEC2:
case GL_UNSIGNED_INT_VEC3:
case GL_UNSIGNED_INT_VEC4:
bind._numeric_type = Shader::SPT_uint;
break;
#ifndef OPENGLES
case GL_DOUBLE:
case GL_DOUBLE_VEC2:
case GL_DOUBLE_VEC3:
case GL_DOUBLE_VEC4:
bind._numeric_type = Shader::SPT_double;
break;
#endif
default:
bind._numeric_type = Shader::SPT_float;
}
// Check if it has a p3d_ prefix - if so, assign special meaning.
if (strncmp(name_buffer, "p3d_", 4) == 0) {
@ -2264,7 +2280,7 @@ disable_shader_vertex_arrays() {
return;
}
for (int i=0; i<(int)_shader->_var_spec.size(); i++) {
for (size_t i = 0; i < _shader->_var_spec.size(); ++i) {
const Shader::ShaderVarSpec &bind = _shader->_var_spec[i];
GLint p = bind._id._seqno;
@ -2389,21 +2405,25 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) {
}
client_pointer += start;
GLenum type = _glgsg->get_numeric_type(numeric_type);
for (int i = 0; i < num_elements; ++i) {
_glgsg->enable_vertex_attrib_array(p);
if (bind._integer) {
_glgsg->_glVertexAttribIPointer(p, num_values, _glgsg->get_numeric_type(numeric_type),
stride, client_pointer);
} else if (numeric_type == GeomEnums::NT_packed_dabc) {
if (numeric_type == GeomEnums::NT_packed_dabc) {
// GL_BGRA is a special accepted value available since OpenGL 3.2.
// It requires us to pass GL_TRUE for normalized.
_glgsg->_glVertexAttribPointer(p, GL_BGRA, GL_UNSIGNED_BYTE,
GL_TRUE, stride, client_pointer);
} else {
_glgsg->_glVertexAttribPointer(p, num_values,
_glgsg->get_numeric_type(numeric_type),
} else if (bind._numeric_type == Shader::SPT_float ||
numeric_type == GeomEnums::NT_float32) {
_glgsg->_glVertexAttribPointer(p, num_values, type,
normalized, stride, client_pointer);
} else if (bind._numeric_type == Shader::SPT_double) {
_glgsg->_glVertexAttribLPointer(p, num_values, type,
stride, client_pointer);
} else {
_glgsg->_glVertexAttribIPointer(p, num_values, type,
stride, client_pointer);
}
if (divisor > 0) {

View File

@ -619,12 +619,29 @@ cg_recurse_parameters(CGparameter parameter, const ShaderType &type,
p._type = arg_type;
p._direction = arg_dir;
p._varying = (vbl == CG_VARYING);
p._integer = (base_type == CG_UINT || base_type == CG_INT ||
base_type == CG_ULONG || base_type == CG_LONG ||
base_type == CG_USHORT || base_type == CG_SHORT ||
base_type == CG_UCHAR || base_type == CG_CHAR);
p._cat = shader_cat.get_safe_ptr();
//NB. Cg does have a CG_DOUBLE type, but at least for the ARB
// profiles and GLSL profiles it just maps to float.
switch (base_type) {
case CG_UINT:
case CG_ULONG:
case CG_USHORT:
case CG_UCHAR:
case CG_BOOL:
p._numeric_type = SPT_uint;
break;
case CG_INT:
case CG_LONG:
case CG_SHORT:
case CG_CHAR:
p._numeric_type = SPT_int;
break;
default:
p._numeric_type = SPT_float;
break;
}
success &= compile_parameter(p, arg_dim);
break;
}
@ -681,7 +698,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
ShaderVarSpec bind;
bind._id = p._id;
bind._append_uv = -1;
bind._integer = p._integer;
bind._numeric_type = p._numeric_type;
if (pieces.size() == 2) {
if (pieces[1] == "position") {

View File

@ -331,6 +331,14 @@ public:
int _seqno;
};
enum ShaderPtrType {
SPT_float,
SPT_double,
SPT_int,
SPT_uint,
SPT_unknown
};
struct ShaderArgInfo {
ShaderArgId _id;
ShaderArgClass _class;
@ -338,18 +346,10 @@ public:
ShaderArgType _type;
ShaderArgDir _direction;
bool _varying;
bool _integer;
ShaderPtrType _numeric_type;
NotifyCategory *_cat;
};
enum ShaderPtrType {
SPT_float,
SPT_double,
SPT_int,
SPT_uint,
SPT_unknown
};
// Container structure for data of parameters ShaderPtrSpec.
struct ShaderPtrData {
private:
@ -425,7 +425,7 @@ public:
PT(InternalName) _name;
int _append_uv;
int _elements;
bool _integer;
ShaderPtrType _numeric_type;
};
struct ShaderPtrSpec {