st/mesa: Add NV12 lowering to PIPE_FORMAT_R8_G8B8_420_UNORM
Some GPUs can sample biplanar formats like NV12 natively, returning the YUV values. Add a lowering type that uses that for sampling and relies on existing colorspace conversions. Reviewed-by: Marek Olšák <marek.olsak@amd.com> Reviewed-by: Rob Clark <robdclark@chromium.org> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6693>
This commit is contained in:
parent
e23bcb69c3
commit
826a10255f
|
@ -4489,6 +4489,7 @@ typedef struct nir_lower_tex_options {
|
|||
unsigned lower_xy_uxvx_external;
|
||||
unsigned lower_ayuv_external;
|
||||
unsigned lower_xyuv_external;
|
||||
unsigned lower_yuv_external;
|
||||
unsigned bt709_external;
|
||||
unsigned bt2020_external;
|
||||
|
||||
|
|
|
@ -427,6 +427,22 @@ lower_xyuv_external(nir_builder *b, nir_tex_instr *tex,
|
|||
options);
|
||||
}
|
||||
|
||||
static void
|
||||
lower_yuv_external(nir_builder *b, nir_tex_instr *tex,
|
||||
const nir_lower_tex_options *options)
|
||||
{
|
||||
b->cursor = nir_after_instr(&tex->instr);
|
||||
|
||||
nir_ssa_def *yuv = sample_plane(b, tex, 0, options);
|
||||
|
||||
convert_yuv_to_rgb(b, tex,
|
||||
nir_channel(b, yuv, 0),
|
||||
nir_channel(b, yuv, 1),
|
||||
nir_channel(b, yuv, 2),
|
||||
nir_imm_float(b, 1.0f),
|
||||
options);
|
||||
}
|
||||
|
||||
/*
|
||||
* Converts a nir_texop_txd instruction to nir_texop_txl with the given lod
|
||||
* computed from the gradients.
|
||||
|
@ -1062,6 +1078,11 @@ nir_lower_tex_block(nir_block *block, nir_builder *b,
|
|||
progress = true;
|
||||
}
|
||||
|
||||
if ((1 << tex->texture_index) & options->lower_yuv_external) {
|
||||
lower_yuv_external(b, tex, options);
|
||||
progress = true;
|
||||
}
|
||||
|
||||
if (sat_mask) {
|
||||
saturate_src(b, tex, sat_mask);
|
||||
progress = true;
|
||||
|
|
|
@ -726,6 +726,16 @@ dri2_update_tex_buffer(struct dri_drawable *drawable,
|
|||
/* no-op */
|
||||
}
|
||||
|
||||
static const struct dri2_format_mapping r8_g8b8_mapping = {
|
||||
DRM_FORMAT_NV12,
|
||||
__DRI_IMAGE_FORMAT_NONE,
|
||||
__DRI_IMAGE_COMPONENTS_Y_UV,
|
||||
PIPE_FORMAT_R8_G8B8_420_UNORM,
|
||||
2,
|
||||
{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
|
||||
{ 1, 1, 1, __DRI_IMAGE_FORMAT_GR88, 2 } }
|
||||
};
|
||||
|
||||
static __DRIimage *
|
||||
dri2_create_image_from_winsys(__DRIscreen *_screen,
|
||||
int width, int height, const struct dri2_format_mapping *map,
|
||||
|
@ -748,6 +758,14 @@ dri2_create_image_from_winsys(__DRIscreen *_screen,
|
|||
PIPE_BIND_SAMPLER_VIEW))
|
||||
tex_usage |= PIPE_BIND_SAMPLER_VIEW;
|
||||
|
||||
/* For NV12, see if we have support for sampling r8_b8g8 */
|
||||
if (!tex_usage && map->pipe_format == PIPE_FORMAT_NV12 &&
|
||||
pscreen->is_format_supported(pscreen, PIPE_FORMAT_R8_G8B8_420_UNORM,
|
||||
screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) {
|
||||
map = &r8_g8b8_mapping;
|
||||
tex_usage |= PIPE_BIND_SAMPLER_VIEW;
|
||||
}
|
||||
|
||||
if (!tex_usage && util_format_is_yuv(map->pipe_format)) {
|
||||
/* YUV format sampling can be emulated by the GL gallium frontend by
|
||||
* using multiple samplers of varying formats.
|
||||
|
|
|
@ -315,6 +315,10 @@ update_shader_samplers(struct st_context *st,
|
|||
|
||||
switch (st_get_view_format(stObj)) {
|
||||
case PIPE_FORMAT_NV12:
|
||||
if (stObj->pt->format == PIPE_FORMAT_R8_G8B8_420_UNORM)
|
||||
/* no additional views needed */
|
||||
break;
|
||||
/* fallthrough */
|
||||
case PIPE_FORMAT_P010:
|
||||
case PIPE_FORMAT_P012:
|
||||
case PIPE_FORMAT_P016:
|
||||
|
|
|
@ -188,6 +188,10 @@ update_textures(struct st_context *st,
|
|||
|
||||
switch (st_get_view_format(stObj)) {
|
||||
case PIPE_FORMAT_NV12:
|
||||
if (stObj->pt->format == PIPE_FORMAT_R8_G8B8_420_UNORM)
|
||||
/* no additional views needed */
|
||||
break;
|
||||
|
||||
/* we need one additional R8G8 view: */
|
||||
tmpl.format = PIPE_FORMAT_RG88_UNORM;
|
||||
tmpl.swizzle_g = PIPE_SWIZZLE_Y; /* tmpl from Y plane is R8 */
|
||||
|
|
|
@ -113,6 +113,25 @@ is_format_supported(struct pipe_screen *screen, enum pipe_format format,
|
|||
return supported;
|
||||
}
|
||||
|
||||
static bool
|
||||
is_nv12_as_r8_g8b8_supported(struct pipe_screen *screen, struct st_egl_image *out,
|
||||
unsigned usage, bool *native_supported)
|
||||
{
|
||||
if (out->format == PIPE_FORMAT_NV12 &&
|
||||
out->texture->format == PIPE_FORMAT_R8_G8B8_420_UNORM &&
|
||||
screen->is_format_supported(screen, PIPE_FORMAT_R8_G8B8_420_UNORM,
|
||||
PIPE_TEXTURE_2D,
|
||||
out->texture->nr_samples,
|
||||
out->texture->nr_storage_samples,
|
||||
usage)) {
|
||||
*native_supported = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the gallium texture of an EGLImage.
|
||||
*/
|
||||
|
@ -136,7 +155,8 @@ st_get_egl_image(struct gl_context *ctx, GLeglImageOES image_handle,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!is_format_supported(screen, out->format, out->texture->nr_samples,
|
||||
if (!is_nv12_as_r8_g8b8_supported(screen, out, usage, native_supported) &&
|
||||
!is_format_supported(screen, out->format, out->texture->nr_samples,
|
||||
out->texture->nr_storage_samples, usage,
|
||||
native_supported)) {
|
||||
/* unable to specify a texture object using the specified EGL image */
|
||||
|
@ -249,8 +269,13 @@ st_bind_egl_image(struct gl_context *ctx,
|
|||
if (!native_supported) {
|
||||
switch (stimg->format) {
|
||||
case PIPE_FORMAT_NV12:
|
||||
if (stimg->texture->format == PIPE_FORMAT_R8_G8B8_420_UNORM) {
|
||||
texFormat = MESA_FORMAT_R8G8B8X8_UNORM;
|
||||
texObj->RequiredTextureImageUnits = 1;
|
||||
} else {
|
||||
texFormat = MESA_FORMAT_R_UNORM8;
|
||||
texObj->RequiredTextureImageUnits = 2;
|
||||
}
|
||||
break;
|
||||
case PIPE_FORMAT_P010:
|
||||
case PIPE_FORMAT_P012:
|
||||
|
|
|
@ -1320,7 +1320,8 @@ st_create_fp_variant(struct st_context *st,
|
|||
|
||||
if (unlikely(key->external.lower_nv12 || key->external.lower_iyuv ||
|
||||
key->external.lower_xy_uxvx || key->external.lower_yx_xuxv ||
|
||||
key->external.lower_ayuv || key->external.lower_xyuv)) {
|
||||
key->external.lower_ayuv || key->external.lower_xyuv ||
|
||||
key->external.lower_yuv)) {
|
||||
|
||||
st_nir_lower_samplers(pipe->screen, state.ir.nir,
|
||||
stfp->shader_program, &stfp->Base);
|
||||
|
@ -1332,6 +1333,7 @@ st_create_fp_variant(struct st_context *st,
|
|||
options.lower_yx_xuxv_external = key->external.lower_yx_xuxv;
|
||||
options.lower_ayuv_external = key->external.lower_ayuv;
|
||||
options.lower_xyuv_external = key->external.lower_xyuv;
|
||||
options.lower_yuv_external = key->external.lower_yuv;
|
||||
NIR_PASS_V(state.ir.nir, nir_lower_tex, &options);
|
||||
finalize = true;
|
||||
}
|
||||
|
@ -1344,7 +1346,8 @@ st_create_fp_variant(struct st_context *st,
|
|||
/* This pass needs to happen *after* nir_lower_sampler */
|
||||
if (unlikely(key->external.lower_nv12 || key->external.lower_iyuv ||
|
||||
key->external.lower_xy_uxvx || key->external.lower_yx_xuxv ||
|
||||
key->external.lower_ayuv || key->external.lower_xyuv)) {
|
||||
key->external.lower_ayuv || key->external.lower_xyuv ||
|
||||
key->external.lower_yuv)) {
|
||||
NIR_PASS_V(state.ir.nir, st_nir_lower_tex_src_plane,
|
||||
~stfp->Base.SamplersUsed,
|
||||
key->external.lower_nv12 || key->external.lower_xy_uxvx ||
|
||||
|
|
|
@ -57,6 +57,7 @@ struct st_external_sampler_key
|
|||
GLuint lower_yx_xuxv; /**< bitmask of 2 plane YUV samplers */
|
||||
GLuint lower_ayuv;
|
||||
GLuint lower_xyuv;
|
||||
GLuint lower_yuv;
|
||||
};
|
||||
|
||||
static inline struct st_external_sampler_key
|
||||
|
@ -79,6 +80,11 @@ st_get_external_sampler_key(struct st_context *st, struct gl_program *prog)
|
|||
|
||||
switch (format) {
|
||||
case PIPE_FORMAT_NV12:
|
||||
if (stObj->pt->format == PIPE_FORMAT_R8_G8B8_420_UNORM) {
|
||||
key.lower_yuv |= (1 << unit);
|
||||
break;
|
||||
}
|
||||
/* fallthrough */
|
||||
case PIPE_FORMAT_P010:
|
||||
case PIPE_FORMAT_P012:
|
||||
case PIPE_FORMAT_P016:
|
||||
|
|
|
@ -496,6 +496,11 @@ get_sampler_view_format(struct st_context *st,
|
|||
/* Use R8_UNORM for video formats */
|
||||
switch (format) {
|
||||
case PIPE_FORMAT_NV12:
|
||||
if (stObj->pt->format == PIPE_FORMAT_R8_G8B8_420_UNORM) {
|
||||
format = PIPE_FORMAT_R8_G8B8_420_UNORM;
|
||||
break;
|
||||
}
|
||||
/* fallthrough */
|
||||
case PIPE_FORMAT_IYUV:
|
||||
format = PIPE_FORMAT_R8_UNORM;
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue