X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fstate_tracker%2Fst_atom_sampler.c;h=b74d47b691fed88ca8f981942bd97bb42fb6aa8d;hb=013d9e40feed336d983b728357e4ce77b871c36d;hp=a1cfa1c34c5929cfd6e565eecce26e6c763846d2;hpb=baab345b192d207236253ce67b320fb32fa67625;p=mesa.git diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c index a1cfa1c34c5..b74d47b691f 100644 --- a/src/mesa/state_tracker/st_atom_sampler.c +++ b/src/mesa/state_tracker/st_atom_sampler.c @@ -43,13 +43,14 @@ #include "st_cb_texture.h" #include "st_format.h" #include "st_atom.h" +#include "st_sampler_view.h" #include "st_texture.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "cso_cache/cso_context.h" -#include "util/u_format.h" +#include "util/format/u_format.h" /** @@ -58,94 +59,56 @@ static GLuint gl_wrap_xlate(GLenum wrap) { - switch (wrap) { - case GL_REPEAT: - return PIPE_TEX_WRAP_REPEAT; - case GL_CLAMP: - return PIPE_TEX_WRAP_CLAMP; - case GL_CLAMP_TO_EDGE: - return PIPE_TEX_WRAP_CLAMP_TO_EDGE; - case GL_CLAMP_TO_BORDER: - return PIPE_TEX_WRAP_CLAMP_TO_BORDER; - case GL_MIRRORED_REPEAT: - return PIPE_TEX_WRAP_MIRROR_REPEAT; - case GL_MIRROR_CLAMP_EXT: - return PIPE_TEX_WRAP_MIRROR_CLAMP; - case GL_MIRROR_CLAMP_TO_EDGE_EXT: - return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE; - case GL_MIRROR_CLAMP_TO_BORDER_EXT: - return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER; - default: - assert(0); - return 0; - } + /* Take advantage of how the enums are defined. */ + static const unsigned table[32] = { + [GL_REPEAT & 0x1f] = PIPE_TEX_WRAP_REPEAT, + [GL_CLAMP & 0x1f] = PIPE_TEX_WRAP_CLAMP, + [GL_CLAMP_TO_EDGE & 0x1f] = PIPE_TEX_WRAP_CLAMP_TO_EDGE, + [GL_CLAMP_TO_BORDER & 0x1f] = PIPE_TEX_WRAP_CLAMP_TO_BORDER, + [GL_MIRRORED_REPEAT & 0x1f] = PIPE_TEX_WRAP_MIRROR_REPEAT, + [GL_MIRROR_CLAMP_EXT & 0x1f] = PIPE_TEX_WRAP_MIRROR_CLAMP, + [GL_MIRROR_CLAMP_TO_EDGE & 0x1f] = PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE, + [GL_MIRROR_CLAMP_TO_BORDER_EXT & 0x1f] = PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER, + }; + + return table[wrap & 0x1f]; } static GLuint gl_filter_to_mip_filter(GLenum filter) { - switch (filter) { - case GL_NEAREST: - case GL_LINEAR: + /* Take advantage of how the enums are defined. */ + if (filter <= GL_LINEAR) return PIPE_TEX_MIPFILTER_NONE; - - case GL_NEAREST_MIPMAP_NEAREST: - case GL_LINEAR_MIPMAP_NEAREST: + if (filter <= GL_LINEAR_MIPMAP_NEAREST) return PIPE_TEX_MIPFILTER_NEAREST; - case GL_NEAREST_MIPMAP_LINEAR: - case GL_LINEAR_MIPMAP_LINEAR: - return PIPE_TEX_MIPFILTER_LINEAR; - - default: - assert(0); - return PIPE_TEX_MIPFILTER_NONE; - } + return PIPE_TEX_MIPFILTER_LINEAR; } static GLuint gl_filter_to_img_filter(GLenum filter) { - switch (filter) { - case GL_NEAREST: - case GL_NEAREST_MIPMAP_NEAREST: - case GL_NEAREST_MIPMAP_LINEAR: - return PIPE_TEX_FILTER_NEAREST; - - case GL_LINEAR: - case GL_LINEAR_MIPMAP_NEAREST: - case GL_LINEAR_MIPMAP_LINEAR: + /* Take advantage of how the enums are defined. */ + if (filter & 1) return PIPE_TEX_FILTER_LINEAR; - default: - assert(0); - return PIPE_TEX_FILTER_NEAREST; - } + return PIPE_TEX_FILTER_NEAREST; } -static void -convert_sampler(struct st_context *st, - struct pipe_sampler_state *sampler, - GLuint texUnit) +/** + * Convert a gl_sampler_object to a pipe_sampler_state object. + */ +void +st_convert_sampler(const struct st_context *st, + const struct gl_texture_object *texobj, + const struct gl_sampler_object *msamp, + float tex_unit_lod_bias, + struct pipe_sampler_state *sampler) { - const struct gl_texture_object *texobj; - struct gl_context *ctx = st->ctx; - const struct gl_sampler_object *msamp; - GLenum texBaseFormat; - - texobj = ctx->Texture.Unit[texUnit]._Current; - if (!texobj) { - texobj = _mesa_get_fallback_texture(ctx, TEXTURE_2D_INDEX); - msamp = &texobj->Sampler; - } else { - msamp = _mesa_get_samplerobj(ctx, texUnit); - } - - texBaseFormat = _mesa_texture_base_format(texobj); - memset(sampler, 0, sizeof(*sampler)); sampler->wrap_s = gl_wrap_xlate(msamp->WrapS); sampler->wrap_t = gl_wrap_xlate(msamp->WrapT); @@ -158,7 +121,13 @@ convert_sampler(struct st_context *st, if (texobj->Target != GL_TEXTURE_RECTANGLE_ARB) sampler->normalized_coords = 1; - sampler->lod_bias = ctx->Texture.Unit[texUnit].LodBias + msamp->LodBias; + sampler->lod_bias = msamp->LodBias + 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 = floorf(sampler->lod_bias * 256) / 256; sampler->min_lod = MAX2(msamp->MinLod, 0.0f); sampler->max_lod = msamp->MaxLod; @@ -172,42 +141,57 @@ convert_sampler(struct st_context *st, assert(sampler->min_lod <= sampler->max_lod); } + /* Check that only wrap modes using the border color have the first bit + * set. + */ + STATIC_ASSERT(PIPE_TEX_WRAP_CLAMP & 0x1); + STATIC_ASSERT(PIPE_TEX_WRAP_CLAMP_TO_BORDER & 0x1); + STATIC_ASSERT(PIPE_TEX_WRAP_MIRROR_CLAMP & 0x1); + STATIC_ASSERT(PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER & 0x1); + STATIC_ASSERT(((PIPE_TEX_WRAP_REPEAT | + PIPE_TEX_WRAP_CLAMP_TO_EDGE | + PIPE_TEX_WRAP_MIRROR_REPEAT | + PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE) & 0x1) == 0); + /* For non-black borders... */ - if (msamp->BorderColor.ui[0] || - msamp->BorderColor.ui[1] || - msamp->BorderColor.ui[2] || - msamp->BorderColor.ui[3]) { - const struct st_texture_object *stobj = st_texture_object_const(texobj); + if (/* This is true if wrap modes are using the border color: */ + (sampler->wrap_s | sampler->wrap_t | sampler->wrap_r) & 0x1 && + (msamp->BorderColor.ui[0] || + msamp->BorderColor.ui[1] || + msamp->BorderColor.ui[2] || + msamp->BorderColor.ui[3])) { const GLboolean is_integer = texobj->_IsIntegerFormat; - const struct pipe_sampler_view *sv = NULL; - union pipe_color_union border_color; - GLuint i; - - /* Just search for the first used view. We can do this because the - swizzle is per-texture, not per context. */ - /* XXX: clean that up to not use the sampler view at all */ - for (i = 0; i < stobj->num_sampler_views; ++i) { - if (stobj->sampler_views[i]) { - sv = stobj->sampler_views[i]; - break; + GLenum texBaseFormat = _mesa_base_tex_image(texobj)->_BaseFormat; + + if (texobj->StencilSampling) + texBaseFormat = GL_STENCIL_INDEX; + + if (st->apply_texture_swizzle_to_border_color) { + const struct st_texture_object *stobj = st_texture_object_const(texobj); + /* XXX: clean that up to not use the sampler view at all */ + const struct st_sampler_view *sv = st_texture_get_current_sampler_view(st, stobj); + + if (sv) { + struct pipe_sampler_view *view = sv->view; + union pipe_color_union tmp; + const unsigned char swz[4] = + { + view->swizzle_r, + view->swizzle_g, + view->swizzle_b, + view->swizzle_a, + }; + + st_translate_color(&msamp->BorderColor, &tmp, + texBaseFormat, is_integer); + + util_format_apply_color_swizzle(&sampler->border_color, + &tmp, swz, is_integer); + } else { + st_translate_color(&msamp->BorderColor, + &sampler->border_color, + texBaseFormat, is_integer); } - } - - if (st->apply_texture_swizzle_to_border_color && sv) { - const unsigned char swz[4] = - { - sv->swizzle_r, - sv->swizzle_g, - sv->swizzle_b, - sv->swizzle_a, - }; - - st_translate_color(&msamp->BorderColor, - &border_color, - texBaseFormat, is_integer); - - util_format_apply_color_swizzle(&sampler->border_color, - &border_color, swz, is_integer); } else { st_translate_color(&msamp->BorderColor, &sampler->border_color, @@ -219,15 +203,45 @@ convert_sampler(struct st_context *st, 0 : (GLuint) msamp->MaxAnisotropy); /* If sampling a depth texture and using shadow comparison */ - if ((texBaseFormat == GL_DEPTH_COMPONENT || - texBaseFormat == GL_DEPTH_STENCIL) && - msamp->CompareMode == GL_COMPARE_R_TO_TEXTURE) { - sampler->compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE; - sampler->compare_func = st_compare_func_to_pipe(msamp->CompareFunc); + if (msamp->CompareMode == GL_COMPARE_R_TO_TEXTURE) { + GLenum texBaseFormat = _mesa_base_tex_image(texobj)->_BaseFormat; + + if (texBaseFormat == GL_DEPTH_COMPONENT || + (texBaseFormat == GL_DEPTH_STENCIL && !texobj->StencilSampling)) { + sampler->compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE; + sampler->compare_func = st_compare_func_to_pipe(msamp->CompareFunc); + } } - sampler->seamless_cube_map = - ctx->Texture.CubeMapSeamless || msamp->CubeMapSeamless; + /* Only set the seamless cube map texture parameter because the per-context + * enable should be ignored and treated as disabled when using texture + * handles, as specified by ARB_bindless_texture. + */ + sampler->seamless_cube_map = msamp->CubeMapSeamless; +} + +/** + * Get a pipe_sampler_state object from a texture unit. + */ +void +st_convert_sampler_from_unit(const struct st_context *st, + struct pipe_sampler_state *sampler, + GLuint texUnit) +{ + const struct gl_texture_object *texobj; + struct gl_context *ctx = st->ctx; + const struct gl_sampler_object *msamp; + + texobj = ctx->Texture.Unit[texUnit]._Current; + assert(texobj); + assert(texobj->Target != GL_TEXTURE_BUFFER); + + msamp = _mesa_get_samplerobj(ctx, texUnit); + + st_convert_sampler(st, texobj, msamp, ctx->Texture.Unit[texUnit].LodBias, + sampler); + + sampler->seamless_cube_map |= ctx->Texture.CubeMapSeamless; } @@ -237,107 +251,167 @@ convert_sampler(struct st_context *st, */ static void update_shader_samplers(struct st_context *st, - unsigned shader_stage, + enum pipe_shader_type shader_stage, const struct gl_program *prog, - unsigned max_units, struct pipe_sampler_state *samplers, - unsigned *num_samplers) + unsigned *out_num_samplers) { - GLuint unit; - GLbitfield samplers_used; - const GLuint old_max = *num_samplers; + struct gl_context *ctx = st->ctx; + GLbitfield samplers_used = prog->SamplersUsed; + GLbitfield free_slots = ~prog->SamplersUsed; + GLbitfield external_samplers_used = prog->ExternalSamplersUsed; + unsigned unit, num_samplers; + struct pipe_sampler_state local_samplers[PIPE_MAX_SAMPLERS]; const struct pipe_sampler_state *states[PIPE_MAX_SAMPLERS]; - samplers_used = prog->SamplersUsed; - - if (*num_samplers == 0 && samplers_used == 0x0) + if (samplers_used == 0x0) { + if (out_num_samplers) + *out_num_samplers = 0; return; + } + + if (!samplers) + samplers = local_samplers; - *num_samplers = 0; + num_samplers = util_last_bit(samplers_used); /* loop over sampler units (aka tex image units) */ - for (unit = 0; unit < max_units; unit++, samplers_used >>= 1) { + for (unit = 0; samplers_used; unit++, samplers_used >>= 1) { struct pipe_sampler_state *sampler = samplers + unit; + unsigned tex_unit = prog->SamplerUnits[unit]; - if (samplers_used & 1) { - const GLuint texUnit = prog->SamplerUnits[unit]; - - convert_sampler(st, sampler, texUnit); + /* Don't update the sampler for TBOs. cso_context will not bind sampler + * states that are NULL. + */ + if (samplers_used & 1 && + ctx->Texture.Unit[tex_unit]._Current->Target != GL_TEXTURE_BUFFER) { + st_convert_sampler_from_unit(st, sampler, tex_unit); states[unit] = sampler; - *num_samplers = unit + 1; - } - else if (samplers_used != 0 || unit < old_max) { + } else { states[unit] = NULL; } - else { - /* if we've reset all the old samplers and we have no more new ones */ + } + + /* For any external samplers with multiplaner YUV, stuff the additional + * sampler states we need at the end. + * + * Just re-use the existing sampler-state from the primary slot. + */ + while (unlikely(external_samplers_used)) { + GLuint unit = u_bit_scan(&external_samplers_used); + GLuint extra = 0; + struct st_texture_object *stObj = + st_get_texture_object(st->ctx, prog, unit); + struct pipe_sampler_state *sampler = samplers + unit; + + /* if resource format matches then YUV wasn't lowered */ + if (!stObj || st_get_view_format(stObj) == stObj->pt->format) + continue; + + switch (st_get_view_format(stObj)) { + case PIPE_FORMAT_NV12: + case PIPE_FORMAT_P010: + case PIPE_FORMAT_P016: + case PIPE_FORMAT_YUYV: + case PIPE_FORMAT_UYVY: + /* we need one additional sampler: */ + extra = u_bit_scan(&free_slots); + states[extra] = sampler; + break; + case PIPE_FORMAT_IYUV: + /* we need two additional samplers: */ + extra = u_bit_scan(&free_slots); + states[extra] = sampler; + extra = u_bit_scan(&free_slots); + states[extra] = sampler; + break; + default: break; } + + num_samplers = MAX2(num_samplers, extra + 1); } - cso_set_samplers(st->cso_context, shader_stage, *num_samplers, states); + cso_set_samplers(st->cso_context, shader_stage, num_samplers, states); + + if (out_num_samplers) + *out_num_samplers = num_samplers; } -static void -update_samplers(struct st_context *st) +void +st_update_vertex_samplers(struct st_context *st) { const struct gl_context *ctx = st->ctx; - update_shader_samplers(st, - PIPE_SHADER_FRAGMENT, - &ctx->FragmentProgram._Current->Base, - ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits, - st->state.samplers[PIPE_SHADER_FRAGMENT], - &st->state.num_samplers[PIPE_SHADER_FRAGMENT]); - update_shader_samplers(st, PIPE_SHADER_VERTEX, - &ctx->VertexProgram._Current->Base, - ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits, - st->state.samplers[PIPE_SHADER_VERTEX], - &st->state.num_samplers[PIPE_SHADER_VERTEX]); + ctx->VertexProgram._Current, + st->state.vert_samplers, + &st->state.num_vert_samplers); +} + + +void +st_update_tessctrl_samplers(struct st_context *st) +{ + const struct gl_context *ctx = st->ctx; - if (ctx->GeometryProgram._Current) { - update_shader_samplers(st, - PIPE_SHADER_GEOMETRY, - &ctx->GeometryProgram._Current->Base, - ctx->Const.Program[MESA_SHADER_GEOMETRY].MaxTextureImageUnits, - st->state.samplers[PIPE_SHADER_GEOMETRY], - &st->state.num_samplers[PIPE_SHADER_GEOMETRY]); - } if (ctx->TessCtrlProgram._Current) { update_shader_samplers(st, PIPE_SHADER_TESS_CTRL, - &ctx->TessCtrlProgram._Current->Base, - ctx->Const.Program[MESA_SHADER_TESS_CTRL].MaxTextureImageUnits, - st->state.samplers[PIPE_SHADER_TESS_CTRL], - &st->state.num_samplers[PIPE_SHADER_TESS_CTRL]); + ctx->TessCtrlProgram._Current, NULL, NULL); } +} + + +void +st_update_tesseval_samplers(struct st_context *st) +{ + const struct gl_context *ctx = st->ctx; + if (ctx->TessEvalProgram._Current) { update_shader_samplers(st, PIPE_SHADER_TESS_EVAL, - &ctx->TessEvalProgram._Current->Base, - ctx->Const.Program[MESA_SHADER_TESS_EVAL].MaxTextureImageUnits, - st->state.samplers[PIPE_SHADER_TESS_EVAL], - &st->state.num_samplers[PIPE_SHADER_TESS_EVAL]); + ctx->TessEvalProgram._Current, NULL, NULL); } - if (ctx->ComputeProgram._Current) { +} + + +void +st_update_geometry_samplers(struct st_context *st) +{ + const struct gl_context *ctx = st->ctx; + + if (ctx->GeometryProgram._Current) { update_shader_samplers(st, - PIPE_SHADER_COMPUTE, - &ctx->ComputeProgram._Current->Base, - ctx->Const.Program[MESA_SHADER_COMPUTE].MaxTextureImageUnits, - st->state.samplers[PIPE_SHADER_COMPUTE], - &st->state.num_samplers[PIPE_SHADER_COMPUTE]); + PIPE_SHADER_GEOMETRY, + ctx->GeometryProgram._Current, NULL, NULL); } } -const struct st_tracked_state st_update_sampler = { - "st_update_sampler", /* name */ - { /* dirty */ - _NEW_TEXTURE, /* mesa */ - 0, /* st */ - }, - update_samplers /* update */ -}; +void +st_update_fragment_samplers(struct st_context *st) +{ + const struct gl_context *ctx = st->ctx; + + update_shader_samplers(st, + PIPE_SHADER_FRAGMENT, + ctx->FragmentProgram._Current, + st->state.frag_samplers, + &st->state.num_frag_samplers); +} + + +void +st_update_compute_samplers(struct st_context *st) +{ + const struct gl_context *ctx = st->ctx; + + if (ctx->ComputeProgram._Current) { + update_shader_samplers(st, + PIPE_SHADER_COMPUTE, + ctx->ComputeProgram._Current, NULL, NULL); + } +}