Module: Mesa Branch: master Commit: e8f71f6ac48c14d3ec923e3cc819d79095a43070 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=e8f71f6ac48c14d3ec923e3cc819d79095a43070
Author: Mike Blumenkrantz <michael.blumenkra...@gmail.com> Date: Mon Jan 25 17:37:29 2021 -0500 mesa/st: add PIPE_CAP_GL_CLAMP when this is not set, this triggers shader and sampler state updates any time a sampler starts or stops using GL_CLAMP, applying bitmasks needed to run nir_lower_tex and setting CLAMP_TO_BORDER/CLAMP_TO_EDGE as necessary to mimic the behavior Reviewed-by: Eric Anholt <e...@anholt.net> Reviewed-by: Marek Olšák <marek.ol...@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8756> --- docs/gallium/screen.rst | 1 + src/gallium/auxiliary/util/u_screen.c | 1 + src/gallium/drivers/nouveau/nvc0/nvc0_screen.c | 1 + src/gallium/include/pipe/p_defines.h | 2 +- src/mesa/main/mtypes.h | 3 ++ src/mesa/main/samplerobj.c | 12 +++++++ src/mesa/main/texparam.c | 12 +++++++ src/mesa/state_tracker/st_atom_sampler.c | 19 +++++++++++ src/mesa/state_tracker/st_atom_shader.c | 44 ++++++++++++++++++++++++++ src/mesa/state_tracker/st_context.c | 8 +++++ src/mesa/state_tracker/st_context.h | 1 + src/mesa/state_tracker/st_program.c | 19 +++++++++++ src/mesa/state_tracker/st_program.h | 6 ++++ 13 files changed, 128 insertions(+), 1 deletion(-) diff --git a/docs/gallium/screen.rst b/docs/gallium/screen.rst index be505ecad8a..ebeef25d94e 100644 --- a/docs/gallium/screen.rst +++ b/docs/gallium/screen.rst @@ -610,6 +610,7 @@ The integer capabilities: * ``PIPE_CAP_MAX_TEXTURE_MB``: Maximum texture size in MB (default is 1024) * ``PIPE_CAP_DEVICE_PROTECTED_CONTENT``: Whether the device support protected / encrypted content. * ``PIPE_CAP_PREFER_REAL_BUFFER_IN_CONSTBUF0``: The state tracker is encouraged to upload constants into a real buffer and bind it into constant buffer 0 instead of binding a user pointer. This may enable a faster codepath in a gallium frontend for drivers that really prefer a real buffer. +* ``PIPE_CAP_GL_CLAMP``: Driver natively supports GL_CLAMP. Required for non-NIR drivers with the GL frontend. NIR drivers with the cap unavailable will have GL_CLAMP lowered to txd/txl with a saturate on the coordinates. .. _pipe_capf: diff --git a/src/gallium/auxiliary/util/u_screen.c b/src/gallium/auxiliary/util/u_screen.c index 1dc853af6bd..08d28f689e6 100644 --- a/src/gallium/auxiliary/util/u_screen.c +++ b/src/gallium/auxiliary/util/u_screen.c @@ -46,6 +46,7 @@ u_pipe_screen_get_param_defaults(struct pipe_screen *pscreen, return 0; case PIPE_CAP_GRAPHICS: + case PIPE_CAP_GL_CLAMP: case PIPE_CAP_MAX_RENDER_TARGETS: return 1; diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c index 4555b35cb16..c4b66894996 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c @@ -300,6 +300,7 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_TEXTURE_SHADOW_LOD: case PIPE_CAP_PACKED_STREAM_OUTPUT: case PIPE_CAP_CLEAR_SCISSORED: + case PIPE_CAP_GL_CLAMP: return 1; case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER: return nouveau_screen(pscreen)->vram_domain & NOUVEAU_BO_VRAM ? 1 : 0; diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h index db595c73728..3d93fb08233 100644 --- a/src/gallium/include/pipe/p_defines.h +++ b/src/gallium/include/pipe/p_defines.h @@ -977,7 +977,7 @@ enum pipe_cap PIPE_CAP_SHADER_ATOMIC_INT64, PIPE_CAP_DEVICE_PROTECTED_CONTENT, PIPE_CAP_PREFER_REAL_BUFFER_IN_CONSTBUF0, - + PIPE_CAP_GL_CLAMP, PIPE_CAP_LAST, /* XXX do not add caps after PIPE_CAP_LAST! */ }; diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 6e257ad3531..d0581b39c06 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -4879,6 +4879,9 @@ struct gl_driver_flags /** Programmable sample location state for gl_context::DrawBuffer */ uint64_t NewSampleLocations; + + /** For GL_CLAMP emulation */ + uint64_t NewSamplersWithClamp; }; struct gl_buffer_binding diff --git a/src/mesa/main/samplerobj.c b/src/mesa/main/samplerobj.c index 7ac0700824e..8a17fb6f14b 100644 --- a/src/mesa/main/samplerobj.c +++ b/src/mesa/main/samplerobj.c @@ -536,6 +536,12 @@ _mesa_set_sampler_wrap(struct gl_context *ctx, struct gl_sampler_object *samp, #define INVALID_PNAME 0x101 #define INVALID_VALUE 0x102 +static inline GLboolean +is_wrap_gl_clamp(GLint param) +{ + return param == GL_CLAMP || param == GL_MIRROR_CLAMP_EXT; +} + static GLuint set_sampler_wrap_s(struct gl_context *ctx, struct gl_sampler_object *samp, GLint param) @@ -544,6 +550,8 @@ set_sampler_wrap_s(struct gl_context *ctx, struct gl_sampler_object *samp, return GL_FALSE; if (validate_texture_wrap_mode(ctx, param)) { flush(ctx); + if (is_wrap_gl_clamp(samp->Attrib.WrapS) != is_wrap_gl_clamp(param)) + ctx->NewDriverState |= ctx->DriverFlags.NewSamplersWithClamp; samp->Attrib.WrapS = param; return GL_TRUE; } @@ -559,6 +567,8 @@ set_sampler_wrap_t(struct gl_context *ctx, struct gl_sampler_object *samp, return GL_FALSE; if (validate_texture_wrap_mode(ctx, param)) { flush(ctx); + if (is_wrap_gl_clamp(samp->Attrib.WrapT) != is_wrap_gl_clamp(param)) + ctx->NewDriverState |= ctx->DriverFlags.NewSamplersWithClamp; samp->Attrib.WrapT = param; return GL_TRUE; } @@ -574,6 +584,8 @@ set_sampler_wrap_r(struct gl_context *ctx, struct gl_sampler_object *samp, return GL_FALSE; if (validate_texture_wrap_mode(ctx, param)) { flush(ctx); + if (is_wrap_gl_clamp(samp->Attrib.WrapR) != is_wrap_gl_clamp(param)) + ctx->NewDriverState |= ctx->DriverFlags.NewSamplersWithClamp; samp->Attrib.WrapR = param; return GL_TRUE; } diff --git a/src/mesa/main/texparam.c b/src/mesa/main/texparam.c index 2f0004458eb..07de903fb3b 100644 --- a/src/mesa/main/texparam.c +++ b/src/mesa/main/texparam.c @@ -239,6 +239,12 @@ _mesa_target_allows_setting_sampler_parameters(GLenum target) } +static inline GLboolean +is_wrap_gl_clamp(GLint param) +{ + return param == GL_CLAMP || param == GL_MIRROR_CLAMP_EXT; +} + /** * Set an integer-valued texture parameter * \return GL_TRUE if legal AND the value changed, GL_FALSE otherwise @@ -317,6 +323,8 @@ set_tex_parameteri(struct gl_context *ctx, return GL_FALSE; if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) { flush(ctx); + if (is_wrap_gl_clamp(texObj->Sampler.Attrib.WrapS) != is_wrap_gl_clamp(params[0])) + ctx->NewDriverState |= ctx->DriverFlags.NewSamplersWithClamp; texObj->Sampler.Attrib.WrapS = params[0]; return GL_TRUE; } @@ -330,6 +338,8 @@ set_tex_parameteri(struct gl_context *ctx, return GL_FALSE; if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) { flush(ctx); + if (is_wrap_gl_clamp(texObj->Sampler.Attrib.WrapT) != is_wrap_gl_clamp(params[0])) + ctx->NewDriverState |= ctx->DriverFlags.NewSamplersWithClamp; texObj->Sampler.Attrib.WrapT = params[0]; return GL_TRUE; } @@ -343,6 +353,8 @@ set_tex_parameteri(struct gl_context *ctx, return GL_FALSE; if (validate_texture_wrap_mode(ctx, texObj->Target, params[0])) { flush(ctx); + if (is_wrap_gl_clamp(texObj->Sampler.Attrib.WrapR) != is_wrap_gl_clamp(params[0])) + ctx->NewDriverState |= ctx->DriverFlags.NewSamplersWithClamp; texObj->Sampler.Attrib.WrapR = params[0]; return GL_TRUE; } diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c index 7416de3dc69..5e9bd37741e 100644 --- a/src/mesa/state_tracker/st_atom_sampler.c +++ b/src/mesa/state_tracker/st_atom_sampler.c @@ -98,6 +98,17 @@ gl_filter_to_img_filter(GLenum filter) return PIPE_TEX_FILTER_NEAREST; } +static inline unsigned +get_border_clamp(unsigned wrap, bool clamp_to_border) +{ + if (wrap == PIPE_TEX_WRAP_CLAMP) + wrap = clamp_to_border ? PIPE_TEX_WRAP_CLAMP_TO_BORDER : + PIPE_TEX_WRAP_CLAMP_TO_EDGE; + else if (wrap == PIPE_TEX_WRAP_MIRROR_CLAMP) + wrap = clamp_to_border ? PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER : + PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE; + return wrap; +} /** * Convert a gl_sampler_object to a pipe_sampler_state object. @@ -123,6 +134,14 @@ st_convert_sampler(const struct st_context *st, } sampler->min_mip_filter = gl_filter_to_mip_filter(msamp->Attrib.MinFilter); + if (st->emulate_gl_clamp) { + bool clamp_to_border = sampler->min_img_filter != PIPE_TEX_FILTER_NEAREST && + sampler->mag_img_filter != PIPE_TEX_FILTER_NEAREST; + sampler->wrap_s = get_border_clamp(sampler->wrap_s, clamp_to_border); + sampler->wrap_t = get_border_clamp(sampler->wrap_t, clamp_to_border); + sampler->wrap_r = get_border_clamp(sampler->wrap_r, clamp_to_border); + } + if (texobj->Target != GL_TEXTURE_RECTANGLE_ARB) sampler->normalized_coords = 1; diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c index b95ac91eddb..9d8311f5165 100644 --- a/src/mesa/state_tracker/st_atom_shader.c +++ b/src/mesa/state_tracker/st_atom_shader.c @@ -73,6 +73,45 @@ get_texture_index(struct gl_context *ctx, const unsigned unit) } +static inline GLboolean +is_wrap_gl_clamp(GLint param) +{ + return param == GL_CLAMP || param == GL_MIRROR_CLAMP_EXT; +} + +static void +update_gl_clamp(struct st_context *st, struct gl_program *prog, uint32_t *gl_clamp) +{ + if (!st->emulate_gl_clamp) + return; + + gl_clamp[0] = gl_clamp[1] = gl_clamp[2] = 0; + GLbitfield samplers_used = prog->SamplersUsed; + unsigned unit; + /* same as st_atom_sampler.c */ + for (unit = 0; samplers_used; unit++, samplers_used >>= 1) { + unsigned tex_unit = prog->SamplerUnits[unit]; + if (samplers_used & 1 && + (st->ctx->Texture.Unit[tex_unit]._Current->Target != GL_TEXTURE_BUFFER || + st->texture_buffer_sampler)) { + const struct gl_texture_object *texobj; + struct gl_context *ctx = st->ctx; + const struct gl_sampler_object *msamp; + + texobj = ctx->Texture.Unit[tex_unit]._Current; + assert(texobj); + + msamp = _mesa_get_samplerobj(ctx, tex_unit); + if (is_wrap_gl_clamp(msamp->Attrib.WrapS)) + gl_clamp[0] |= BITFIELD64_BIT(unit); + if (is_wrap_gl_clamp(msamp->Attrib.WrapT)) + gl_clamp[1] |= BITFIELD64_BIT(unit); + if (is_wrap_gl_clamp(msamp->Attrib.WrapR)) + gl_clamp[2] |= BITFIELD64_BIT(unit); + } + } +} + /** * Update fragment program state/atom. This involves translating the * Mesa fragment program into a gallium fragment program and binding it. @@ -143,6 +182,7 @@ st_update_fp( struct st_context *st ) } key.external = st_get_external_sampler_key(st, &stfp->Base); + update_gl_clamp(st, st->ctx->FragmentProgram._Current, key.gl_clamp); simple_mtx_lock(&st->ctx->Shared->Mutex); shader = st_get_fp_variant(st, stfp, &key)->base.driver_shader; @@ -218,6 +258,8 @@ st_update_vp( struct st_context *st ) key.lower_ucp = st->ctx->Transform.ClipPlanesEnabled; } + update_gl_clamp(st, st->ctx->VertexProgram._Current, key.gl_clamp); + simple_mtx_lock(&st->ctx->Shared->Mutex); st->vp_variant = st_get_vp_variant(st, stvp, &key); simple_mtx_unlock(&st->ctx->Shared->Mutex); @@ -283,6 +325,8 @@ st_update_common_program(struct st_context *st, struct gl_program *prog, } + update_gl_clamp(st, prog, key.gl_clamp); + simple_mtx_lock(&st->ctx->Shared->Mutex); void *result = st_get_common_variant(st, stp, &key)->driver_shader; simple_mtx_unlock(&st->ctx->Shared->Mutex); diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index 68a0a193ef2..6268e897f98 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -574,6 +574,12 @@ st_init_driver_flags(struct st_context *st) f->NewNvConservativeRasterization = ST_NEW_RASTERIZER; f->NewNvConservativeRasterizationParams = ST_NEW_RASTERIZER; f->NewIntelConservativeRasterization = ST_NEW_RASTERIZER; + + if (st->emulate_gl_clamp) + f->NewSamplersWithClamp = ST_NEW_SAMPLERS | + ST_NEW_VS_STATE | ST_NEW_TCS_STATE | + ST_NEW_TES_STATE | ST_NEW_GS_STATE | + ST_NEW_FS_STATE | ST_NEW_CS_STATE; } @@ -690,6 +696,8 @@ st_create_context_priv(struct gl_context *ctx, struct pipe_context *pipe, !!(screen->get_param(screen, PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK) & (PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50 | PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_R600)); + st->emulate_gl_clamp = + !screen->get_param(screen, PIPE_CAP_GL_CLAMP); st->texture_buffer_sampler = screen->get_param(screen, PIPE_CAP_TEXTURE_BUFFER_SAMPLER); st->has_time_elapsed = diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index f7b5ef61d02..63657e95c29 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -182,6 +182,7 @@ struct st_context boolean needs_texcoord_semantic; boolean apply_texture_swizzle_to_border_color; + boolean emulate_gl_clamp; boolean texture_buffer_sampler; /* On old libGL's for linux we need to invalidate the drawables diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 68918ba833a..ae052247f74 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -783,6 +783,15 @@ st_create_vp_variant(struct st_context *st, finalize = true; } + if (st->emulate_gl_clamp && + (key->gl_clamp[0] || key->gl_clamp[1] || key->gl_clamp[2])) { + nir_lower_tex_options tex_opts = {0}; + tex_opts.saturate_s = key->gl_clamp[0]; + tex_opts.saturate_t = key->gl_clamp[1]; + tex_opts.saturate_r = key->gl_clamp[2]; + NIR_PASS_V(state.ir.nir, nir_lower_tex, &tex_opts); + } + if (finalize || !st->allow_st_finalize_nir_twice) { st_finalize_nir(st, &stvp->Base, stvp->shader_program, state.ir.nir, true, false); @@ -1310,6 +1319,16 @@ st_create_fp_variant(struct st_context *st, finalize = true; } + if (st->emulate_gl_clamp && + (key->gl_clamp[0] || key->gl_clamp[1] || key->gl_clamp[2])) { + nir_lower_tex_options tex_opts = {0}; + tex_opts.saturate_s = key->gl_clamp[0]; + tex_opts.saturate_t = key->gl_clamp[1]; + tex_opts.saturate_r = key->gl_clamp[2]; + NIR_PASS_V(state.ir.nir, nir_lower_tex, &tex_opts); + finalize = true; + } + assert(!(key->bitmap && key->drawpixels)); /* glBitmap */ diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h index f87339a5472..ad7830c2a0c 100644 --- a/src/mesa/state_tracker/st_program.h +++ b/src/mesa/state_tracker/st_program.h @@ -151,6 +151,9 @@ struct st_fp_variant_key uint8_t texture_index[MAX_NUM_FRAGMENT_REGISTERS_ATI]; struct st_external_sampler_key external; + + /* bitmask of sampler units; PIPE_CAP_GL_CLAMP */ + uint32_t gl_clamp[3]; }; /** @@ -209,6 +212,9 @@ struct st_common_variant_key * not for the driver. */ bool is_draw_shader; + + /* bitmask of sampler units; PIPE_CAP_GL_CLAMP */ + uint32_t gl_clamp[3]; }; _______________________________________________ mesa-commit mailing list mesa-commit@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-commit