On Thu, Apr 24, 2014 at 8:50 PM, Eric Anholt <e...@anholt.net> wrote: > Instead of walking 6 shader stages for each of the 96 combined texture > image units, now we just walk the samplers used in each shader stage. > > With cairo-perf-trace on Xephyr with glamor, I'm seeing a -6.50518% +/- > 2.55601% effect on runtime (n=22) since the "drop _EnabledUnits" change. > No significant performance difference on an apitrace of minecraft (n=442). > --- > src/mesa/main/texstate.c | 122 > ++++++++++++++++++++++++++++------------------- > 1 file changed, 73 insertions(+), 49 deletions(-) > > diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c > index 0082caf..3a7e227 100644 > --- a/src/mesa/main/texstate.c > +++ b/src/mesa/main/texstate.c > @@ -515,68 +515,92 @@ update_texgen(struct gl_context *ctx) > } > } > > +static struct gl_texture_object * > +update_single_program_texture(struct gl_context *ctx, struct gl_program > *prog, > + int s) > +{ > + gl_texture_index target_index; > + struct gl_texture_unit *texUnit; > + struct gl_texture_object *texObj; > + int unit; > + > + if (!(prog->SamplersUsed & (1 << s))) > + return NULL; > + > + unit = prog->SamplerUnits[s]; > + texUnit = &ctx->Texture.Unit[unit]; > + > + /* Note: If more than one bit was set in TexturesUsed[unit], then we > should > + * have had the draw call rejected already. From the GL 4.4 > specification, > + * section 7.10 ("Samplers"): > + * > + * "It is not allowed to have variables of different sampler types > + * pointing to the same texture image unit within a program > + * object. This situation can only be detected at the next rendering > + * command issued which triggers shader invocations, and an > + * INVALID_OPERATION error will then be generated." > + */ > + target_index = ffs(prog->TexturesUsed[unit]) - 1; > + texObj = texUnit->CurrentTex[target_index]; > + > + struct gl_sampler_object *sampler = texUnit->Sampler ? > + texUnit->Sampler : &texObj->Sampler; > + > + if (likely(texObj)) { > + if (_mesa_is_texture_complete(texObj, sampler)) > + return texObj; > + > + _mesa_test_texobj_completeness(ctx, texObj); > + if (_mesa_is_texture_complete(texObj, sampler)) > + return texObj; > + } > + > + /* If we've reached this point, we didn't find a complete texture of the > + * shader's target. From the GL 4.4 core specification, section 11.1.3.5 > + * ("Texture Access"): > + * > + * "If a sampler is used in a shader and the sampler’s associated > + * texture is not complete, as defined in section 8.17, (0, 0, 0, 1) > + * will be returned for a non-shadow sampler and 0 for a shadow > + * sampler." > + * > + * Mesa implements this by creating a hidden texture object with a pixel > of > + * that value. > + */ > + texObj = _mesa_get_fallback_texture(ctx, target_index); > + assert(texObj); > + > + return texObj; > +} > + > static void > update_program_texture_state(struct gl_context *ctx, struct gl_program > **prog, > BITSET_WORD *enabled_texture_units) > { > - GLuint unit; > int i; > > - for (unit = 0; unit < ctx->Const.MaxCombinedTextureImageUnits; unit++) { > - struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; > - GLbitfield enabledTargets = 0x0; > - GLuint texIndex; > - > - for (i = 0; i < MESA_SHADER_STAGES; i++) { > - if (prog[i]) > - enabledTargets |= prog[i]->TexturesUsed[unit]; > - } > + for (i = 0; i < MESA_SHADER_STAGES; i++) { > + int s; > > - if (enabledTargets == 0x0) { > - /* neither vertex nor fragment processing uses this unit */ > + if (!prog[i]) > continue; > - } > - > - for (texIndex = 0; texIndex < NUM_TEXTURE_TARGETS; texIndex++) { > - if (enabledTargets & (1 << texIndex)) { > - struct gl_texture_object *texObj = texUnit->CurrentTex[texIndex]; > - struct gl_sampler_object *sampler = texUnit->Sampler ? > - texUnit->Sampler : &texObj->Sampler; > - > - if (!_mesa_is_texture_complete(texObj, sampler)) { > - _mesa_test_texobj_completeness(ctx, texObj); > - } > - if (_mesa_is_texture_complete(texObj, sampler)) { > - _mesa_reference_texobj(&texUnit->_Current, texObj); > - break; > - } > - } > - } > > - if (texIndex == NUM_TEXTURE_TARGETS) { > - /* If we get here it means the shader is expecting a texture > - * object, but there isn't one (or it's incomplete). Use the > - * fallback texture. > - */ > + /* We can't only do the shifting trick as the loop condition because if > + * sampler 31 is active, the next iteration tries to shift by 32, > which is > + * undefined. > + */ > + for (s = 0; s < MAX_SAMPLERS && (1 << s) <= prog[i]->SamplersUsed; > s++) {
I could be confused, but are you trying to walk over all set bits of SamplersUsed? You can do this with something like u_bit_scan() which basically does tmp = prog[i]->SamplersUsed; while (tmp) { s = ffs(tmp) - 1; tmp &= ~(1 << s); ... } This should avoid pointless iteration when there are just a few bits set. If the expectation is that 1..n bits are all going to be set, then this provides little advantage. -ilia > struct gl_texture_object *texObj; > - gl_texture_index texTarget; > - > - texTarget = (gl_texture_index) (ffs(enabledTargets) - 1); > - texObj = _mesa_get_fallback_texture(ctx, texTarget); > > - assert(texObj); > - if (!texObj) { > - /* invalid fallback texture: don't enable the texture unit */ > - continue; > + texObj = update_single_program_texture(ctx, prog[i], s); > + if (texObj) { > + int unit = prog[i]->SamplerUnits[s]; > + _mesa_reference_texobj(&ctx->Texture.Unit[unit]._Current, > texObj); > + BITSET_SET(enabled_texture_units, unit); > + ctx->Texture._MaxEnabledTexImageUnit = > + MAX2(ctx->Texture._MaxEnabledTexImageUnit, (int)unit); > } > - > - _mesa_reference_texobj(&texUnit->_Current, texObj); > } > - > - /* if we get here, we know this texture unit is enabled */ > - BITSET_SET(enabled_texture_units, unit); > - ctx->Texture._MaxEnabledTexImageUnit = > - MAX2(ctx->Texture._MaxEnabledTexImageUnit, (int)unit); > } > > if (prog[MESA_SHADER_FRAGMENT]) { > -- > 1.9.2 > > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/mesa-dev > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev