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 <eric@anholt.net> Reviewed-by: Marek Olšák <marek.olsak@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8756>
This commit is contained in:
parent
10e71d5c9a
commit
e8f71f6ac4
|
@ -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:
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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! */
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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];
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue