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_xy_uxvx_external;
|
||||||
unsigned lower_ayuv_external;
|
unsigned lower_ayuv_external;
|
||||||
unsigned lower_xyuv_external;
|
unsigned lower_xyuv_external;
|
||||||
|
unsigned lower_yuv_external;
|
||||||
unsigned bt709_external;
|
unsigned bt709_external;
|
||||||
unsigned bt2020_external;
|
unsigned bt2020_external;
|
||||||
|
|
||||||
|
|
|
@ -427,6 +427,22 @@ lower_xyuv_external(nir_builder *b, nir_tex_instr *tex,
|
||||||
options);
|
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
|
* Converts a nir_texop_txd instruction to nir_texop_txl with the given lod
|
||||||
* computed from the gradients.
|
* computed from the gradients.
|
||||||
|
@ -1062,6 +1078,11 @@ nir_lower_tex_block(nir_block *block, nir_builder *b,
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((1 << tex->texture_index) & options->lower_yuv_external) {
|
||||||
|
lower_yuv_external(b, tex, options);
|
||||||
|
progress = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (sat_mask) {
|
if (sat_mask) {
|
||||||
saturate_src(b, tex, sat_mask);
|
saturate_src(b, tex, sat_mask);
|
||||||
progress = true;
|
progress = true;
|
||||||
|
|
|
@ -726,6 +726,16 @@ dri2_update_tex_buffer(struct dri_drawable *drawable,
|
||||||
/* no-op */
|
/* 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 *
|
static __DRIimage *
|
||||||
dri2_create_image_from_winsys(__DRIscreen *_screen,
|
dri2_create_image_from_winsys(__DRIscreen *_screen,
|
||||||
int width, int height, const struct dri2_format_mapping *map,
|
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))
|
PIPE_BIND_SAMPLER_VIEW))
|
||||||
tex_usage |= 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)) {
|
if (!tex_usage && util_format_is_yuv(map->pipe_format)) {
|
||||||
/* YUV format sampling can be emulated by the GL gallium frontend by
|
/* YUV format sampling can be emulated by the GL gallium frontend by
|
||||||
* using multiple samplers of varying formats.
|
* using multiple samplers of varying formats.
|
||||||
|
|
|
@ -315,6 +315,10 @@ update_shader_samplers(struct st_context *st,
|
||||||
|
|
||||||
switch (st_get_view_format(stObj)) {
|
switch (st_get_view_format(stObj)) {
|
||||||
case PIPE_FORMAT_NV12:
|
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_P010:
|
||||||
case PIPE_FORMAT_P012:
|
case PIPE_FORMAT_P012:
|
||||||
case PIPE_FORMAT_P016:
|
case PIPE_FORMAT_P016:
|
||||||
|
|
|
@ -188,6 +188,10 @@ update_textures(struct st_context *st,
|
||||||
|
|
||||||
switch (st_get_view_format(stObj)) {
|
switch (st_get_view_format(stObj)) {
|
||||||
case PIPE_FORMAT_NV12:
|
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: */
|
/* we need one additional R8G8 view: */
|
||||||
tmpl.format = PIPE_FORMAT_RG88_UNORM;
|
tmpl.format = PIPE_FORMAT_RG88_UNORM;
|
||||||
tmpl.swizzle_g = PIPE_SWIZZLE_Y; /* tmpl from Y plane is R8 */
|
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;
|
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.
|
* Return the gallium texture of an EGLImage.
|
||||||
*/
|
*/
|
||||||
|
@ -136,7 +155,8 @@ st_get_egl_image(struct gl_context *ctx, GLeglImageOES image_handle,
|
||||||
return false;
|
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,
|
out->texture->nr_storage_samples, usage,
|
||||||
native_supported)) {
|
native_supported)) {
|
||||||
/* unable to specify a texture object using the specified EGL image */
|
/* 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) {
|
if (!native_supported) {
|
||||||
switch (stimg->format) {
|
switch (stimg->format) {
|
||||||
case PIPE_FORMAT_NV12:
|
case PIPE_FORMAT_NV12:
|
||||||
texFormat = MESA_FORMAT_R_UNORM8;
|
if (stimg->texture->format == PIPE_FORMAT_R8_G8B8_420_UNORM) {
|
||||||
texObj->RequiredTextureImageUnits = 2;
|
texFormat = MESA_FORMAT_R8G8B8X8_UNORM;
|
||||||
|
texObj->RequiredTextureImageUnits = 1;
|
||||||
|
} else {
|
||||||
|
texFormat = MESA_FORMAT_R_UNORM8;
|
||||||
|
texObj->RequiredTextureImageUnits = 2;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case PIPE_FORMAT_P010:
|
case PIPE_FORMAT_P010:
|
||||||
case PIPE_FORMAT_P012:
|
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 ||
|
if (unlikely(key->external.lower_nv12 || key->external.lower_iyuv ||
|
||||||
key->external.lower_xy_uxvx || key->external.lower_yx_xuxv ||
|
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,
|
st_nir_lower_samplers(pipe->screen, state.ir.nir,
|
||||||
stfp->shader_program, &stfp->Base);
|
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_yx_xuxv_external = key->external.lower_yx_xuxv;
|
||||||
options.lower_ayuv_external = key->external.lower_ayuv;
|
options.lower_ayuv_external = key->external.lower_ayuv;
|
||||||
options.lower_xyuv_external = key->external.lower_xyuv;
|
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);
|
NIR_PASS_V(state.ir.nir, nir_lower_tex, &options);
|
||||||
finalize = true;
|
finalize = true;
|
||||||
}
|
}
|
||||||
|
@ -1344,7 +1346,8 @@ st_create_fp_variant(struct st_context *st,
|
||||||
/* This pass needs to happen *after* nir_lower_sampler */
|
/* This pass needs to happen *after* nir_lower_sampler */
|
||||||
if (unlikely(key->external.lower_nv12 || key->external.lower_iyuv ||
|
if (unlikely(key->external.lower_nv12 || key->external.lower_iyuv ||
|
||||||
key->external.lower_xy_uxvx || key->external.lower_yx_xuxv ||
|
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,
|
NIR_PASS_V(state.ir.nir, st_nir_lower_tex_src_plane,
|
||||||
~stfp->Base.SamplersUsed,
|
~stfp->Base.SamplersUsed,
|
||||||
key->external.lower_nv12 || key->external.lower_xy_uxvx ||
|
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_yx_xuxv; /**< bitmask of 2 plane YUV samplers */
|
||||||
GLuint lower_ayuv;
|
GLuint lower_ayuv;
|
||||||
GLuint lower_xyuv;
|
GLuint lower_xyuv;
|
||||||
|
GLuint lower_yuv;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct st_external_sampler_key
|
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) {
|
switch (format) {
|
||||||
case PIPE_FORMAT_NV12:
|
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_P010:
|
||||||
case PIPE_FORMAT_P012:
|
case PIPE_FORMAT_P012:
|
||||||
case PIPE_FORMAT_P016:
|
case PIPE_FORMAT_P016:
|
||||||
|
|
|
@ -496,6 +496,11 @@ get_sampler_view_format(struct st_context *st,
|
||||||
/* Use R8_UNORM for video formats */
|
/* Use R8_UNORM for video formats */
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case PIPE_FORMAT_NV12:
|
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:
|
case PIPE_FORMAT_IYUV:
|
||||||
format = PIPE_FORMAT_R8_UNORM;
|
format = PIPE_FORMAT_R8_UNORM;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue