Extremely experimental support for GL_ARB_shader_image_load_store

This commit is contained in:
rdb 2014-06-15 12:57:58 +00:00
parent 37f9858e1b
commit e4747ebf50
4 changed files with 109 additions and 2 deletions

View File

@ -1584,7 +1584,36 @@ reset() {
GLP(GetFloatv)(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &max_anisotropy);
_max_anisotropy = (PN_stdfloat)max_anisotropy;
_supports_anisotropy = true;
}
}
// Check availability of image read/write functionality in shaders.
_max_image_units = 0;
if (is_at_least_gl_version(4, 2) || has_extension("GL_ARB_shader_image_load_store")) {
_glBindImageTexture = (PFNGLBINDIMAGETEXTUREPROC)
get_extension_func(GLPREFIX_QUOTED, "BindImageTexture");
GLP(GetIntegerv)(GL_MAX_IMAGE_UNITS, &_max_image_units);
} else if (has_extension("GL_EXT_shader_image_load_store")) {
_glBindImageTexture = (PFNGLBINDIMAGETEXTUREPROC)
get_extension_func(GLPREFIX_QUOTED, "BindImageTextureEXT");
GLP(GetIntegerv)(GL_MAX_IMAGE_UNITS_EXT, &_max_image_units);
}
// Check availability of multi-bind functions.
_supports_multi_bind = false;
if (is_at_least_gl_version(4, 4) || has_extension("GL_ARB_multi_bind")) {
_glBindImageTextures = (PFNGLBINDIMAGETEXTURESPROC)
get_extension_func(GLPREFIX_QUOTED, "BindImageTextures");
if (_glBindImageTextures != NULL) {
_supports_multi_bind = true;
} else {
GLCAT.warning()
<< "ARB_multi_bind advertised as supported by OpenGL runtime, but could not get pointers to extension function.\n";
}
}
report_my_gl_errors();

View File

@ -170,6 +170,8 @@ typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size,
typedef void (APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value);
typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount);
typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
typedef void (APIENTRYP PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
typedef void (APIENTRYP PFNGLBINDIMAGETEXTURESPROC) (GLuint first, GLsizei count, const GLuint *textures);
#endif // OPENGLES
#endif // __EDG__
@ -522,6 +524,8 @@ protected:
int _num_active_texture_stages;
PN_stdfloat _max_anisotropy;
bool _supports_anisotropy;
GLint _max_image_units;
bool _supports_multi_bind;
#ifdef OPENGLES
bool _supports_depth24;
@ -687,6 +691,8 @@ public:
PFNGLPATCHPARAMETERIPROC _glPatchParameteri;
PFNGLDRAWARRAYSINSTANCEDPROC _glDrawArraysInstanced;
PFNGLDRAWELEMENTSINSTANCEDPROC _glDrawElementsInstanced;
PFNGLBINDIMAGETEXTUREPROC _glBindImageTexture;
PFNGLBINDIMAGETEXTURESPROC _glBindImageTextures;
#endif // OPENGLES
GLenum _edge_clamp;

View File

@ -290,9 +290,11 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) {
return;
}
}
gsg->_glUseProgram(_glsl_program);
// Analyze the uniforms and put them in _glsl_parameter_map
if (_glsl_parameter_map.size() == 0) {
int seqno = 0, texunitno = 0;
int seqno = 0, texunitno = 0, imgunitno = 0;
string noprefix;
GLint param_count, param_maxlength, param_size;
GLenum param_type;
@ -653,6 +655,28 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) {
case GL_INT_VEC4:
GLCAT.warning() << "Panda does not support passing integers to shaders (yet)!\n";
continue;
#ifndef OPENGLES
case GL_IMAGE_1D_EXT:
case GL_IMAGE_2D_EXT:
case GL_IMAGE_3D_EXT:
case GL_IMAGE_CUBE_EXT:
case GL_IMAGE_2D_ARRAY_EXT:
case GL_INT_IMAGE_1D_EXT:
case GL_INT_IMAGE_2D_EXT:
case GL_INT_IMAGE_3D_EXT:
case GL_INT_IMAGE_CUBE_EXT:
case GL_INT_IMAGE_2D_ARRAY_EXT:
case GL_UNSIGNED_INT_IMAGE_1D_EXT:
case GL_UNSIGNED_INT_IMAGE_2D_EXT:
case GL_UNSIGNED_INT_IMAGE_3D_EXT:
case GL_UNSIGNED_INT_IMAGE_CUBE_EXT:
case GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT:
// This won't really change at runtime, so we might as well
// bind once and then forget about it.
gsg->_glUniform1i(p, imgunitno++);
_glsl_img_inputs.push_back(InternalName::make(param_name));
continue;
#endif
default:
GLCAT.warning() << "Ignoring unrecognized GLSL parameter type!\n";
}
@ -793,6 +817,7 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) {
s->_var_spec.push_back(bind);
}
}
gsg->_glUseProgram(0);
}
gsg->report_my_gl_errors();
@ -1465,6 +1490,51 @@ update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg) {
}
}
// Now bind all the 'image units'; a bit of an esoteric OpenGL feature right now.
int num_image_units = min(_glsl_img_inputs.size(), (size_t)gsg->_max_image_units);
if (num_image_units > 0 && _shader->get_language() == Shader::SL_GLSL) {
GLuint *multi_img = NULL;
// If we support multi-bind, prepare an array.
if (gsg->_supports_multi_bind && num_image_units > 1) {
multi_img = new GLuint[num_image_units];
}
for (int i = 0; i < num_image_units; ++i) {
const InternalName *name = _glsl_img_inputs[i];
Texture *tex = gsg->_target_shader->get_shader_input_texture(name);
GLuint gl_tex = 0;
if (tex != NULL) {
int view = gsg->get_current_tex_view_offset();
CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tex->prepare_now(view, gsg->_prepared_objects, gsg));
if (gtc != (TextureContext*)NULL) {
gl_tex = gtc->_index;
}
}
if (multi_img != NULL) {
// Put in array so we can multi-bind later.
multi_img[i] = gl_tex;
} else {
// We don't support multi-bind, so bind now in the same way that multi-bind would have done it.
if (gl_tex == 0) {
gsg->_glBindImageTexture(i, 0, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8);
} else {
GLint internal_format = gsg->get_internal_image_format(tex);
gsg->_glBindImageTexture(i, gl_tex, 0, GL_TRUE, 0, GL_READ_WRITE, internal_format);
}
}
}
if (multi_img != NULL) {
gsg->_glBindImageTextures(0, num_image_units, multi_img);
delete[] multi_img;
}
}
#if defined(HAVE_CG) && !defined(OPENGLES)
cg_report_errors();
#endif

View File

@ -77,6 +77,8 @@ private:
pvector <GLint> _glsl_parameter_map;
pvector<CPT(InternalName)> _glsl_img_inputs;
int _stage_offset;
// Avoid using this! It merely exists so the
// destructor has access to the extension functions.