diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c index 98c4b8afdc7..f9faf67df8e 100644 --- a/src/mesa/main/attrib.c +++ b/src/mesa/main/attrib.c @@ -277,6 +277,7 @@ _mesa_PushAttrib(GLbitfield mask) unsigned num_tex_used = ctx->Texture.NumCurrentTexUsed; for (u = 0; u < num_tex_used; u++) { head->Texture.LodBias[u] = ctx->Texture.Unit[u].LodBias; + head->Texture.LodBiasQuantized[u] = ctx->Texture.Unit[u].LodBiasQuantized; for (tex = 0; tex < NUM_TEXTURE_TARGETS; tex++) { struct gl_texture_object *dst = &head->Texture.SavedObj[u][tex]; @@ -618,6 +619,7 @@ pop_texture_group(struct gl_context *ctx, struct gl_texture_attrib_node *texstat memcpy(destUnit, unit, sizeof(*unit)); destUnit->_CurrentCombine = NULL; ctx->Texture.Unit[u].LodBias = texstate->LodBias[u]; + ctx->Texture.Unit[u].LodBiasQuantized = texstate->LodBiasQuantized[u]; } } diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index a28baf50f1b..4be2c7f773d 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -1180,6 +1180,7 @@ struct gl_texgen struct gl_texture_unit { GLfloat LodBias; /**< for biasing mipmap levels */ + float LodBiasQuantized; /**< to reduce pipe_sampler_state variants */ /** Texture targets that have a non-default texture bound */ GLbitfield _BoundTextures; @@ -5094,6 +5095,7 @@ struct gl_texture_attrib_node GLuint NumTexSaved; struct gl_fixedfunc_texture_unit FixedFuncUnit[MAX_TEXTURE_COORD_UNITS]; GLfloat LodBias[MAX_TEXTURE_UNITS]; + float LodBiasQuantized[MAX_TEXTURE_UNITS]; /** Saved default texture object state. */ struct gl_texture_object SavedDefaultObj[NUM_TEXTURE_TARGETS]; diff --git a/src/mesa/main/samplerobj.c b/src/mesa/main/samplerobj.c index 7fba7de24cd..0ee8f7c1160 100644 --- a/src/mesa/main/samplerobj.c +++ b/src/mesa/main/samplerobj.c @@ -692,7 +692,7 @@ set_sampler_lod_bias(struct gl_context *ctx, struct gl_sampler_object *samp, flush(ctx); samp->Attrib.LodBias = param; - samp->Attrib.state.lod_bias = param; + samp->Attrib.state.lod_bias = util_quantize_lod_bias(param); return GL_TRUE; } diff --git a/src/mesa/main/texenv.c b/src/mesa/main/texenv.c index 9f7125d51b6..e6b82636f70 100644 --- a/src/mesa/main/texenv.c +++ b/src/mesa/main/texenv.c @@ -471,6 +471,7 @@ _mesa_texenvfv_indexed( struct gl_context* ctx, GLuint texunit, GLenum target, return; FLUSH_VERTICES(ctx, _NEW_TEXTURE_OBJECT, GL_TEXTURE_BIT); texUnit->LodBias = param[0]; + texUnit->LodBiasQuantized = util_quantize_lod_bias(param[0]); } else { TE_ERROR(GL_INVALID_ENUM, "glTexEnv(pname=%s)", pname); diff --git a/src/mesa/main/texparam.c b/src/mesa/main/texparam.c index 1515a97b24b..4121548b1e2 100644 --- a/src/mesa/main/texparam.c +++ b/src/mesa/main/texparam.c @@ -786,7 +786,7 @@ set_tex_parameterf(struct gl_context *ctx, if (texObj->Sampler.Attrib.LodBias != params[0]) { flush(ctx); texObj->Sampler.Attrib.LodBias = params[0]; - texObj->Sampler.Attrib.state.lod_bias = params[0]; + texObj->Sampler.Attrib.state.lod_bias = util_quantize_lod_bias(params[0]); return GL_TRUE; } break; diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c index cbdfb1899cf..6ad0eddfb50 100644 --- a/src/mesa/main/texstate.c +++ b/src/mesa/main/texstate.c @@ -76,6 +76,7 @@ _mesa_copy_texture_state( const struct gl_context *src, struct gl_context *dst ) /* per-unit state */ for (u = 0; u < src->Const.MaxCombinedTextureImageUnits; u++) { dst->Texture.Unit[u].LodBias = src->Texture.Unit[u].LodBias; + dst->Texture.Unit[u].LodBiasQuantized = src->Texture.Unit[u].LodBiasQuantized; /* * XXX strictly speaking, we should compare texture names/ids and diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c index 49af7bea85d..35bf2dc8c75 100644 --- a/src/mesa/state_tracker/st_atom_sampler.c +++ b/src/mesa/state_tracker/st_atom_sampler.c @@ -94,12 +94,6 @@ st_convert_sampler(const struct st_context *st, sampler->normalized_coords = 1; sampler->lod_bias += tex_unit_lod_bias; - /* Reduce the number of states by allowing only the values that AMD GCN - * can represent. Apps use lod_bias for smooth transitions to bigger mipmap - * levels. - */ - sampler->lod_bias = CLAMP(sampler->lod_bias, -16, 16); - sampler->lod_bias = roundf(sampler->lod_bias * 256) / 256; /* Check that only wrap modes using the border color have the first bit * set. @@ -184,7 +178,7 @@ st_convert_sampler_from_unit(const struct st_context *st, msamp = _mesa_get_samplerobj(ctx, texUnit); - st_convert_sampler(st, texobj, msamp, ctx->Texture.Unit[texUnit].LodBias, + st_convert_sampler(st, texobj, msamp, ctx->Texture.Unit[texUnit].LodBiasQuantized, sampler); sampler->seamless_cube_map |= ctx->Texture.CubeMapSeamless; diff --git a/src/util/u_math.h b/src/util/u_math.h index 0223ecb9965..7c989a3963d 100644 --- a/src/util/u_math.h +++ b/src/util/u_math.h @@ -780,6 +780,20 @@ util_is_vbo_upload_ratio_too_large(unsigned draw_vertex_count, bool util_invert_mat4x4(float *out, const float *m); +/* Quantize the lod bias value to reduce the number of sampler state + * variants in gallium because apps use it for smooth mipmap transitions, + * thrashing cso_cache and degrading performance. + * + * This quantization matches the AMD hw specification, so having more + * precision would have no effect anyway. + */ +static inline float +util_quantize_lod_bias(float lod) +{ + lod = CLAMP(lod, -16, 16); + return roundf(lod * 256) / 256; +} + #ifdef __cplusplus } #endif