Use multibind when binding textures and samplers to a shader

This commit is contained in:
rdb 2015-12-21 17:59:28 +01:00
parent c093fc0fa4
commit dc0f40cadd
3 changed files with 79 additions and 8 deletions

View File

@ -10134,6 +10134,20 @@ apply_white_texture() {
GL_RGBA, GL_UNSIGNED_BYTE, data); GL_RGBA, GL_UNSIGNED_BYTE, data);
} }
////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::get_white_texture
// Access: Private
// Description: Returns a white dummy texture. This is useful to
// bind to a texture slot when a texture is missing.
////////////////////////////////////////////////////////////////////
GLuint CLP(GraphicsStateGuardian)::
get_white_texture() {
if (_white_texture == 0) {
apply_white_texture();
}
return _white_texture;
}
#ifndef NDEBUG #ifndef NDEBUG
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: GLGraphicsStateGuardian::update_show_usage_texture_bindings // Function: GLGraphicsStateGuardian::update_show_usage_texture_bindings

View File

@ -529,6 +529,7 @@ protected:
#endif #endif
void apply_white_texture(); void apply_white_texture();
GLuint get_white_texture();
#ifndef NDEBUG #ifndef NDEBUG
void update_show_usage_texture_bindings(int show_stage_index); void update_show_usage_texture_bindings(int show_stage_index);

View File

@ -2366,7 +2366,22 @@ update_shader_texture_bindings(ShaderContext *prev) {
} }
#endif #endif
for (int i = 0; i < (int)_shader->_tex_spec.size(); ++i) { size_t num_textures = _shader->_tex_spec.size();
GLuint *textures;
GLuint *samplers;
#ifdef OPENGLES
static const bool multi_bind = false;
#else
bool multi_bind = false;
if (_glgsg->_supports_multi_bind && _glgsg->_supports_sampler_objects) {
// Prepare to multi-bind the textures and samplers.
multi_bind = true;
textures = (GLuint *)alloca(sizeof(GLuint) * num_textures);
samplers = (GLuint *)alloca(sizeof(GLuint) * num_textures);
}
#endif
for (size_t i = 0; i < num_textures; ++i) {
Shader::ShaderTexSpec &spec = _shader->_tex_spec[i]; Shader::ShaderTexSpec &spec = _shader->_tex_spec[i];
const InternalName *id = spec._name; const InternalName *id = spec._name;
@ -2377,8 +2392,13 @@ update_shader_texture_bindings(ShaderContext *prev) {
if (tex.is_null()) { if (tex.is_null()) {
// Apply a white texture in order to make it easier to use a shader // Apply a white texture in order to make it easier to use a shader
// that takes a texture on a model that doesn't have a texture applied. // that takes a texture on a model that doesn't have a texture applied.
if (multi_bind) {
textures[i] = _glgsg->get_white_texture();
samplers[i] = 0;
} else {
_glgsg->_glActiveTexture(GL_TEXTURE0 + i); _glgsg->_glActiveTexture(GL_TEXTURE0 + i);
_glgsg->apply_white_texture(); _glgsg->apply_white_texture();
}
continue; continue;
} }
@ -2397,6 +2417,10 @@ update_shader_texture_bindings(ShaderContext *prev) {
CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tex->prepare_now(view, _glgsg->_prepared_objects, _glgsg)); CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tex->prepare_now(view, _glgsg->_prepared_objects, _glgsg));
if (gtc == NULL) { if (gtc == NULL) {
if (multi_bind) {
textures[i] = 0;
samplers[i] = 0;
}
continue; continue;
} }
@ -2412,6 +2436,10 @@ update_shader_texture_bindings(ShaderContext *prev) {
if (gl_use_bindless_texture && _glgsg->_supports_bindless_texture) { if (gl_use_bindless_texture && _glgsg->_supports_bindless_texture) {
// We demand the real texture, since we won't be able // We demand the real texture, since we won't be able
// to change the texture properties after this point. // to change the texture properties after this point.
if (multi_bind) {
textures[i] = 0;
samplers[i] = 0;
}
if (!_glgsg->update_texture(gtc, true)) { if (!_glgsg->update_texture(gtc, true)) {
continue; continue;
} }
@ -2439,6 +2467,28 @@ update_shader_texture_bindings(ShaderContext *prev) {
// Bindless texturing wasn't supported or didn't work, so // Bindless texturing wasn't supported or didn't work, so
// let's just bind the texture normally. // let's just bind the texture normally.
#ifndef OPENGLES
if (multi_bind) {
// Multi-bind case.
if (!_glgsg->update_texture(gtc, false)) {
textures[i] = 0;
} else {
gtc->set_active(true);
textures[i] = gtc->_index;
}
SamplerContext *sc = sampler.prepare_now(_glgsg->get_prepared_objects(), _glgsg);
if (sc == NULL) {
samplers[i] = 0;
} else {
CLP(SamplerContext) *gsc = DCAST(CLP(SamplerContext), sc);
gsc->enqueue_lru(&_glgsg->_prepared_objects->_sampler_object_lru);
samplers[i] = gsc->_index;
}
} else
#endif // !OPENGLES
{
// Non-multibind case.
_glgsg->_glActiveTexture(GL_TEXTURE0 + i); _glgsg->_glActiveTexture(GL_TEXTURE0 + i);
if (!_glgsg->update_texture(gtc, false)) { if (!_glgsg->update_texture(gtc, false)) {
continue; continue;
@ -2446,8 +2496,14 @@ update_shader_texture_bindings(ShaderContext *prev) {
_glgsg->apply_texture(gtc); _glgsg->apply_texture(gtc);
_glgsg->apply_sampler(i, sampler, gtc); _glgsg->apply_sampler(i, sampler, gtc);
} }
}
#ifndef OPENGLES #ifndef OPENGLES
if (multi_bind && num_textures > 0) {
_glgsg->_glBindTextures(0, num_textures, textures);
_glgsg->_glBindSamplers(0, num_textures, samplers);
}
if (barriers != 0) { if (barriers != 0) {
// Issue a memory barrier prior to this shader's execution. // Issue a memory barrier prior to this shader's execution.
_glgsg->issue_memory_barrier(barriers); _glgsg->issue_memory_barrier(barriers);