On Fri, Sep 2, 2016 at 9:45 PM, Rob Clark <robdcl...@gmail.com> wrote: > Support multi-planar YUV for external EGLImage's (currently just in the > dma-buf import path) by lowering to multiple texture fetch's for each > plane and CSC in shader. > > Currently lots of TODO's, only NV12 implemented so far, only wired up in > frag shader, etc, etc.. > --- > src/gallium/auxiliary/util/u_inlines.h | 4 +- > src/gallium/include/pipe/p_state.h | 9 +++ > src/gallium/include/state_tracker/st_api.h | 3 + > src/gallium/state_trackers/dri/dri2.c | 111 > ++++++++++++++++++++++------ > src/gallium/state_trackers/dri/dri_screen.c | 11 +++ > src/mesa/main/mtypes.h | 16 ++++ > src/mesa/program/ir_to_mesa.cpp | 1 + > src/mesa/state_tracker/st_atom_sampler.c | 52 ++++++++++++- > src/mesa/state_tracker/st_atom_shader.c | 27 +++++++ > src/mesa/state_tracker/st_atom_texture.c | 71 +++++++++++++++++- > src/mesa/state_tracker/st_cb_eglimage.c | 18 +++++ > src/mesa/state_tracker/st_context.c | 10 ++- > src/mesa/state_tracker/st_glsl_to_nir.cpp | 1 + > src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 4 + > src/mesa/state_tracker/st_manager.c | 1 + > src/mesa/state_tracker/st_program.c | 18 +++++ > src/mesa/state_tracker/st_program.h | 3 + > 17 files changed, 330 insertions(+), 30 deletions(-) > > diff --git a/src/gallium/auxiliary/util/u_inlines.h > b/src/gallium/auxiliary/util/u_inlines.h > index c2a0b08..b7b8313 100644 > --- a/src/gallium/auxiliary/util/u_inlines.h > +++ b/src/gallium/auxiliary/util/u_inlines.h > @@ -136,8 +136,10 @@ pipe_resource_reference(struct pipe_resource **ptr, > struct pipe_resource *tex) > struct pipe_resource *old_tex = *ptr; > > if (pipe_reference_described(&(*ptr)->reference, &tex->reference, > - > (debug_reference_descriptor)debug_describe_resource)) > + > (debug_reference_descriptor)debug_describe_resource)) { > + pipe_resource_reference(&old_tex->next, NULL); > old_tex->screen->resource_destroy(old_tex->screen, old_tex); > + } > *ptr = tex; > } > > diff --git a/src/gallium/include/pipe/p_state.h > b/src/gallium/include/pipe/p_state.h > index ebd0337..4a88da6 100644 > --- a/src/gallium/include/pipe/p_state.h > +++ b/src/gallium/include/pipe/p_state.h > @@ -498,6 +498,15 @@ struct pipe_resource > > unsigned bind; /**< bitmask of PIPE_BIND_x */ > unsigned flags; /**< bitmask of PIPE_RESOURCE_FLAG_x */ > + > + /** > + * For planar images, ie. YUV EGLImage external, etc, pointer to the > + * next plane. > + * > + * TODO might be useful for dealing w/ z32s8 too, since at least a > + * couple drivers split these out into separate buffers internally. > + */ > + struct pipe_resource *next;
I'm not a fan of this but I don't have a better idea. > }; > > > diff --git a/src/gallium/include/state_tracker/st_api.h > b/src/gallium/include/state_tracker/st_api.h > index 21d5177..06abfc5 100644 > --- a/src/gallium/include/state_tracker/st_api.h > +++ b/src/gallium/include/state_tracker/st_api.h > @@ -200,6 +200,9 @@ struct st_egl_image > /* this is owned by the caller */ > struct pipe_resource *texture; > > + /* format only differs from texture->format for multi-planar (YUV): */ > + enum pipe_format format; > + > unsigned level; > unsigned layer; > }; > diff --git a/src/gallium/state_trackers/dri/dri2.c > b/src/gallium/state_trackers/dri/dri2.c > index fdab499..91eabc8 100644 > --- a/src/gallium/state_trackers/dri/dri2.c > +++ b/src/gallium/state_trackers/dri/dri2.c > @@ -83,6 +83,20 @@ static int convert_fourcc(int format, int > *dri_components_p) > format = __DRI_IMAGE_FORMAT_GR88; > dri_components = __DRI_IMAGE_COMPONENTS_RG; > break; > + /* > + * For multi-planar YUV formats, we return the format of the first > + * plane only. Since there is only one caller which supports multi- > + * planar YUV it gets to figure out the remaining planes on it's > + * own. > + */ > + case __DRI_IMAGE_FOURCC_YUV420: > + format = __DRI_IMAGE_FORMAT_R8; > + dri_components = __DRI_IMAGE_COMPONENTS_Y_U_V; > + break; > + case __DRI_IMAGE_FOURCC_NV12: > + format = __DRI_IMAGE_FORMAT_R8; > + dri_components = __DRI_IMAGE_COMPONENTS_Y_UV; > + break; > default: > return -1; > } > @@ -90,6 +104,11 @@ static int convert_fourcc(int format, int > *dri_components_p) > return format; > } > > +/* NOTE this probably isn't going to do the right thing for YUV images > + * (but I think the same can be said for intel_query_image()). I think > + * only needed for exporting dmabuf's, so I think I won't loose much > + * sleep over it. > + */ > static int convert_to_fourcc(int format) > { > switch(format) { > @@ -762,14 +781,16 @@ dri2_lookup_egl_image(struct dri_screen *screen, void > *handle) > static __DRIimage * > dri2_create_image_from_winsys(__DRIscreen *_screen, > int width, int height, int format, > - struct winsys_handle *whandle, > + int num_handles, struct winsys_handle *whandle, > void *loaderPrivate) > { > struct dri_screen *screen = dri_screen(_screen); > + struct pipe_screen *pscreen = screen->base.screen; > __DRIimage *img; > struct pipe_resource templ; > unsigned tex_usage; > enum pipe_format pf; > + int i; > > tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; > > @@ -783,19 +804,47 @@ dri2_create_image_from_winsys(__DRIscreen *_screen, > > memset(&templ, 0, sizeof(templ)); > templ.bind = tex_usage; > - templ.format = pf; > templ.target = screen->target; > templ.last_level = 0; > - templ.width0 = width; > - templ.height0 = height; > templ.depth0 = 1; > templ.array_size = 1; > > - img->texture = > screen->base.screen->resource_from_handle(screen->base.screen, > - &templ, whandle, PIPE_HANDLE_USAGE_READ_WRITE); > - if (!img->texture) { > - FREE(img); > - return NULL; > + for (i = num_handles - 1; i >= 0; i--) { > + struct pipe_resource *tex; > + > + /* TODO: something a lot less ugly */ > + switch (i) { > + case 0: > + templ.width0 = width; > + templ.height0 = height; > + templ.format = pf; > + break; > + case 1: > + templ.width0 = width / 2; > + templ.height0 = height / 2; > + templ.format = (num_handles == 2) ? > + PIPE_FORMAT_RG88_UNORM : /* NV12, etc */ > + PIPE_FORMAT_R8_UNORM; /* I420, etc */ > + break; > + case 2: > + templ.width0 = width / 2; > + templ.height0 = height / 2; > + templ.format = PIPE_FORMAT_R8_UNORM; > + break; > + default: > + unreachable("too many planes!"); > + } > + > + tex = pscreen->resource_from_handle(pscreen, > + &templ, &whandle[i], PIPE_HANDLE_USAGE_READ_WRITE); > + if (!tex) { > + pipe_resource_reference(&img->texture, NULL); > + FREE(img); > + return NULL; > + } > + > + tex->next = img->texture; > + img->texture = tex; > } > > img->level = 0; > @@ -826,7 +875,7 @@ dri2_create_image_from_name(__DRIscreen *_screen, > whandle.stride = pitch * util_format_get_blocksize(pf); > > return dri2_create_image_from_winsys(_screen, width, height, format, > - &whandle, loaderPrivate); > + 1, &whandle, loaderPrivate); > } > > static __DRIimage * > @@ -836,12 +885,25 @@ dri2_create_image_from_fd(__DRIscreen *_screen, > int *offsets, unsigned *error, > int *dri_components, void *loaderPrivate) > { > - struct winsys_handle whandle; > + struct winsys_handle whandles[3]; > int format; > __DRIimage *img = NULL; > unsigned err = __DRI_IMAGE_ERROR_SUCCESS; > + int expected_num_fds, i; > > - if (num_fds != 1) { > + switch (fourcc) { > + case __DRI_IMAGE_FOURCC_YUV420: > + expected_num_fds = 3; > + break; > + case __DRI_IMAGE_FOURCC_NV12: > + expected_num_fds = 2; > + break; > + default: > + expected_num_fds = 1; > + break; > + } > + > + if (num_fds != expected_num_fds) { > err = __DRI_IMAGE_ERROR_BAD_MATCH; > goto exit; > } > @@ -852,19 +914,22 @@ dri2_create_image_from_fd(__DRIscreen *_screen, > goto exit; > } > > - if (fds[0] < 0) { > - err = __DRI_IMAGE_ERROR_BAD_ALLOC; > - goto exit; > - } > + memset(whandles, 0, sizeof(whandles)); > > - memset(&whandle, 0, sizeof(whandle)); > - whandle.type = DRM_API_HANDLE_TYPE_FD; > - whandle.handle = (unsigned)fds[0]; > - whandle.stride = (unsigned)strides[0]; > - whandle.offset = (unsigned)offsets[0]; > + for (i = 0; i < num_fds; i++) { > + if (fds[i] < 0) { > + err = __DRI_IMAGE_ERROR_BAD_ALLOC; > + goto exit; > + } > + > + whandles[i].type = DRM_API_HANDLE_TYPE_FD; > + whandles[i].handle = (unsigned)fds[i]; > + whandles[i].stride = (unsigned)strides[i]; > + whandles[i].offset = (unsigned)offsets[i]; > + } > > img = dri2_create_image_from_winsys(_screen, width, height, format, > - &whandle, loaderPrivate); > + num_fds, whandles, loaderPrivate); > if(img == NULL) > err = __DRI_IMAGE_ERROR_BAD_ALLOC; > > @@ -1067,7 +1132,7 @@ dri2_from_names(__DRIscreen *screen, int width, int > height, int format, > whandle.offset = offsets[0]; > > img = dri2_create_image_from_winsys(screen, width, height, format, > - &whandle, loaderPrivate); > + 1, &whandle, loaderPrivate); > if (img == NULL) > return NULL; > > diff --git a/src/gallium/state_trackers/dri/dri_screen.c > b/src/gallium/state_trackers/dri/dri_screen.c > index 79bcb5a..aa0ad09 100644 > --- a/src/gallium/state_trackers/dri/dri_screen.c > +++ b/src/gallium/state_trackers/dri/dri_screen.c > @@ -334,6 +334,17 @@ dri_get_egl_image(struct st_manager *smapi, > > stimg->texture = NULL; > pipe_resource_reference(&stimg->texture, img->texture); > + switch (img->dri_components) { > + case __DRI_IMAGE_COMPONENTS_Y_U_V: > + stimg->format = PIPE_FORMAT_IYUV; > + break; > + case __DRI_IMAGE_COMPONENTS_Y_UV: > + stimg->format = PIPE_FORMAT_NV12; > + break; > + default: > + stimg->format = img->texture->format; > + break; > + } > stimg->level = img->level; > stimg->layer = img->layer; > > diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h > index 4013ca7..4500376 100644 > --- a/src/mesa/main/mtypes.h > +++ b/src/mesa/main/mtypes.h > @@ -45,6 +45,7 @@ > #include "compiler/shader_enums.h" > #include "main/formats.h" /* MESA_FORMAT_COUNT */ > #include "compiler/glsl/list.h" > +#include "util/bitscan.h" > > > #ifdef __cplusplus > @@ -1926,6 +1927,7 @@ struct gl_program > GLbitfield TexturesUsed[MAX_COMBINED_TEXTURE_IMAGE_UNITS]; /**< > TEXTURE_x_BIT bitmask */ > GLbitfield SamplersUsed; /**< Bitfield of which samplers are used */ > GLbitfield ShadowSamplers; /**< Texture units used for shadow sampling. */ > + GLbitfield ExternalSamplersUsed; /**< Texture units used for > samplerExternalOES */ > > GLboolean UsesGather; /**< Does this program use gather4 at all? */ > > @@ -2457,6 +2459,20 @@ struct gl_linked_shader > struct gl_shader_info info; > }; > > +static inline GLbitfield gl_external_samplers(struct gl_linked_shader > *shader) > +{ > + GLbitfield external_samplers = 0; > + GLbitfield mask = shader->active_samplers; > + > + while (mask) { > + int idx = u_bit_scan(&mask); > + if (shader->SamplerTargets[idx] == TEXTURE_EXTERNAL_INDEX) > + external_samplers |= (1 << idx); > + } > + > + return external_samplers; > +} > + > /** > * A GLSL shader object. > */ > diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp > index e74d94f..9b6b5e8 100644 > --- a/src/mesa/program/ir_to_mesa.cpp > +++ b/src/mesa/program/ir_to_mesa.cpp > @@ -2921,6 +2921,7 @@ get_mesa_program(struct gl_context *ctx, > > prog->SamplersUsed = shader->active_samplers; > prog->ShadowSamplers = shader->shadow_samplers; > + prog->ExternalSamplersUsed = gl_external_samplers(shader); > _mesa_update_shader_textures_used(shader_program, prog); > > /* Set the gl_FragDepth layout. */ > diff --git a/src/mesa/state_tracker/st_atom_sampler.c > b/src/mesa/state_tracker/st_atom_sampler.c > index 6b36ac7..ffdec08 100644 > --- a/src/mesa/state_tracker/st_atom_sampler.c > +++ b/src/mesa/state_tracker/st_atom_sampler.c > @@ -243,13 +243,12 @@ update_shader_samplers(struct st_context *st, > struct pipe_sampler_state *samplers, > unsigned *num_samplers) > { > - GLuint unit; > - GLbitfield samplers_used; > + GLbitfield samplers_used = prog->SamplersUsed; > + GLbitfield external_samplers_used = prog->ExternalSamplersUsed; > + GLuint unit, last_used = 0; > const GLuint old_max = *num_samplers; > const struct pipe_sampler_state *states[PIPE_MAX_SAMPLERS]; > > - samplers_used = prog->SamplersUsed; > - > if (*num_samplers == 0 && samplers_used == 0x0) > return; > > @@ -264,6 +263,7 @@ update_shader_samplers(struct st_context *st, > > convert_sampler(st, sampler, texUnit); > states[unit] = sampler; > + last_used = unit; > *num_samplers = unit + 1; > } > else if (samplers_used != 0 || unit < old_max) { > @@ -275,6 +275,50 @@ update_shader_samplers(struct st_context *st, > } > } > > + /* 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)) { > + struct gl_context *ctx = st->ctx; > + GLuint unit = u_bit_scan(&external_samplers_used); > + const GLuint texUnit = prog->SamplerUnits[unit]; > + struct gl_texture_object *texObj = ctx->Texture.Unit[texUnit]._Current; > + struct st_texture_object *stObj = st_texture_object(texObj); > + struct pipe_sampler_state *sampler = samplers + unit; > + enum pipe_format view_format; > + > + if (!texObj) > + continue; > + > + view_format = > + stObj->surface_based ? stObj->surface_format : stObj->pt->format; > + > + switch (view_format) { > + case PIPE_FORMAT_NV12: > + /* we need one additional sampler: */ > + states[++last_used] = sampler; > + break; > + case PIPE_FORMAT_IYUV: > + /* we need two additional samplers: */ > + states[++last_used] = sampler; > + states[++last_used] = sampler; > + break; > + default: > + break; > + } > + > + /* TODO The OES_EGL_image_external spec allows YUV external images to > + * consume multiple sampler slots (and even provides a way to query > + * this).. but we should fail w/ a gl error somewhere sooner if the > + * user exceeds this.. > + */ > + assert(last_used < PIPE_MAX_SAMPLERS); > + } > + > + *num_samplers = MAX2(*num_samplers, last_used + 1); > + > cso_set_samplers(st->cso_context, shader_stage, *num_samplers, states); > } > > diff --git a/src/mesa/state_tracker/st_atom_shader.c > b/src/mesa/state_tracker/st_atom_shader.c > index 7a23469..154069d 100644 > --- a/src/mesa/state_tracker/st_atom_shader.c > +++ b/src/mesa/state_tracker/st_atom_shader.c > @@ -51,6 +51,7 @@ > #include "st_context.h" > #include "st_atom.h" > #include "st_program.h" > +#include "st_texture.h" > > > /** Compress the fog function enums into a 2-bit value */ > @@ -142,6 +143,32 @@ update_fp( struct st_context *st ) > } > } > > + if (unlikely(stfp->Base.Base.ExternalSamplersUsed)) { > + struct gl_context *ctx = st->ctx; > + unsigned mask = stfp->Base.Base.ExternalSamplersUsed; > + while (mask) { > + unsigned unit = u_bit_scan(&mask); > + unsigned texUnit = stfp->Base.Base.SamplerUnits[unit]; > + struct gl_texture_object *texObj = > ctx->Texture.Unit[texUnit]._Current; > + struct st_texture_object *stObj = st_texture_object(texObj); > + enum pipe_format view_format; > + > + view_format = > + stObj->surface_based ? stObj->surface_format : stObj->pt->format; > + > + switch (view_format) { > + case PIPE_FORMAT_NV12: > + key.lower_nv12 |= (1 << unit); > + break; > + case PIPE_FORMAT_IYUV: > + key.lower_iyuv |= (1 << unit); > + break; > + default: > + break; > + } > + } > + } > + > st->fp_variant = st_get_fp_variant(st, stfp, &key); > > st_reference_fragprog(st, &st->fp, stfp); > diff --git a/src/mesa/state_tracker/st_atom_texture.c > b/src/mesa/state_tracker/st_atom_texture.c > index b647117..909e724 100644 > --- a/src/mesa/state_tracker/st_atom_texture.c > +++ b/src/mesa/state_tracker/st_atom_texture.c > @@ -405,6 +405,15 @@ update_single_texture(struct st_context *st, > } > } > > + switch (view_format) { > + case PIPE_FORMAT_NV12: > + case PIPE_FORMAT_IYUV: > + view_format = PIPE_FORMAT_R8_UNORM; > + break; > + default: > + break; > + } > + > *sampler_view = > st_get_texture_sampler_view_from_stobj(st, stObj, view_format, > glsl_version); > @@ -423,7 +432,8 @@ update_textures(struct st_context *st, > { > const GLuint old_max = *num_textures; > GLbitfield samplers_used = prog->SamplersUsed; > - GLuint unit; > + GLbitfield external_samplers_used = prog->ExternalSamplersUsed; > + GLuint unit, last_used = 0; > struct gl_shader_program *shader = > st->ctx->_Shader->CurrentProgram[mesa_shader]; > unsigned glsl_version = shader ? shader->Version : 0; > @@ -454,9 +464,68 @@ update_textures(struct st_context *st, > break; > } > > + if (sampler_view) > + last_used = unit; > + > pipe_sampler_view_reference(&(sampler_views[unit]), sampler_view); > } > > + /* For any external samplers with multiplaner YUV, stuff the additional > + * sampler views we need at the end. > + * > + * Trying to cache the sampler view in the stObj looks painful, so just > + * re-create the sampler view for the extra planes each time. Main use > + * case is video playback (ie. fps games wouldn't be using this) so I > + * guess no point to try to optimize this feature. > + */ > + while (unlikely(external_samplers_used)) { > + struct gl_context *ctx = st->ctx; > + GLuint unit = u_bit_scan(&external_samplers_used); > + const GLuint texUnit = prog->SamplerUnits[unit]; > + struct gl_texture_object *texObj = ctx->Texture.Unit[texUnit]._Current; > + struct st_texture_object *stObj = st_texture_object(texObj); > + enum pipe_format view_format; > + struct pipe_sampler_view tmpl; > + > + if (!texObj) > + continue; > + > + /* use original view as template: */ > + tmpl = *sampler_views[unit]; > + > + view_format = > + stObj->surface_based ? stObj->surface_format : stObj->pt->format; > + > + switch (view_format) { > + case PIPE_FORMAT_NV12: > + /* we need one additional R8G8 view: */ > + tmpl.format = PIPE_FORMAT_RG88_UNORM; > + tmpl.swizzle_g = PIPE_SWIZZLE_Y; /* tmpl from Y plane is R8 */ > + sampler_views[++last_used] = > + st->pipe->create_sampler_view(st->pipe, stObj->pt->next, > &tmpl); > + break; > + case PIPE_FORMAT_IYUV: > + /* we need two additional R8 views: */ > + tmpl.format = PIPE_FORMAT_R8_UNORM; > + sampler_views[++last_used] = > + st->pipe->create_sampler_view(st->pipe, stObj->pt->next, > &tmpl); > + sampler_views[++last_used] = > + st->pipe->create_sampler_view(st->pipe, > stObj->pt->next->next, &tmpl); > + break; > + default: > + break; > + } > + > + /* TODO The OES_EGL_image_external spec allows YUV external images to > + * consume multiple sampler slots (and even provides a way to query > + * this).. but we should fail w/ a gl error somewhere sooner if the > + * user exceeds this.. > + */ > + assert(last_used < PIPE_MAX_SAMPLERS); > + } > + > + *num_textures = MAX2(*num_textures, last_used + 1); > + > cso_set_sampler_views(st->cso_context, > shader_stage, > *num_textures, > diff --git a/src/mesa/state_tracker/st_cb_eglimage.c > b/src/mesa/state_tracker/st_cb_eglimage.c > index 1782d15..7bea565 100644 > --- a/src/mesa/state_tracker/st_cb_eglimage.c > +++ b/src/mesa/state_tracker/st_cb_eglimage.c > @@ -119,6 +119,24 @@ st_bind_surface(struct gl_context *ctx, GLenum target, > > texFormat = st_pipe_format_to_mesa_format(ps->format); > > + /* TODO RequiredTextureImageUnits should probably be reset back > + * to 1 somewhere if different texture is bound?? > + */ > + if (texFormat == MESA_FORMAT_NONE) { > + switch (ps->format) { > + case PIPE_FORMAT_NV12: > + texFormat = MESA_FORMAT_R_UNORM8; > + texObj->RequiredTextureImageUnits = 2; > + break; > + case PIPE_FORMAT_IYUV: > + texFormat = MESA_FORMAT_R_UNORM8; > + texObj->RequiredTextureImageUnits = 3; > + break; > + default: > + unreachable("bad YUV format!"); > + } > + } > + > _mesa_init_teximage_fields(ctx, texImage, > ps->width, ps->height, 1, 0, internalFormat, > texFormat); > diff --git a/src/mesa/state_tracker/st_context.c > b/src/mesa/state_tracker/st_context.c > index ddc11a4..0e3b491 100644 > --- a/src/mesa/state_tracker/st_context.c > +++ b/src/mesa/state_tracker/st_context.c > @@ -254,11 +254,19 @@ void st_invalidate_state(struct gl_context * ctx, > GLbitfield new_state) > st->active_states = st_get_active_states(ctx); > } > > - if (new_state & _NEW_TEXTURE) > + if (new_state & _NEW_TEXTURE) { > st->dirty |= st->active_states & > (ST_NEW_SAMPLER_VIEWS | > ST_NEW_SAMPLERS | > ST_NEW_IMAGE_UNITS); > + // TODO we need to do this for all shader stages > + if (st->fp && st->fp->Base.Base.ExternalSamplersUsed) { > + /* TODO check if external imgs have actually changed # of > + * samplers used (ie. between RGB / 2-plane YUV / 3-plane YUV) > + */ > + st->dirty |= ST_NEW_FS_STATE; > + } You don't want to use st->fp here, because it comes from the previous draw call, not the current state. ctx->FragmentProgram._Current is the correct variable here. > + } > > if (new_state & _NEW_PROGRAM_CONSTANTS) > st->dirty |= st->active_states & ST_NEW_CONSTANTS; > diff --git a/src/mesa/state_tracker/st_glsl_to_nir.cpp > b/src/mesa/state_tracker/st_glsl_to_nir.cpp > index 307bf3e..ac9cc9d 100644 > --- a/src/mesa/state_tracker/st_glsl_to_nir.cpp > +++ b/src/mesa/state_tracker/st_glsl_to_nir.cpp > @@ -422,6 +422,7 @@ st_nir_get_mesa_program(struct gl_context *ctx, > > prog->SamplersUsed = shader->active_samplers; > prog->ShadowSamplers = shader->shadow_samplers; > + prog->ExternalSamplersUsed = gl_external_samplers(shader); > _mesa_update_shader_textures_used(shader_program, prog); > > _mesa_reference_program(ctx, &shader->Program, prog); > diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp > b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp > index b7e47db..3f1f8fc 100644 > --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp > +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp > @@ -4346,6 +4346,10 @@ count_resources(glsl_to_tgsi_visitor *v, gl_program > *prog) > } > } > } > + > + if (inst->tex_target == TEXTURE_EXTERNAL_INDEX) > + prog->ExternalSamplersUsed |= 1 << inst->sampler.index; > + > if (inst->buffer.file != PROGRAM_UNDEFINED && ( > is_resource_instruction(inst->op) || > inst->op == TGSI_OPCODE_STORE)) { > diff --git a/src/mesa/state_tracker/st_manager.c > b/src/mesa/state_tracker/st_manager.c > index e2da054..fece5d5 100644 > --- a/src/mesa/state_tracker/st_manager.c > +++ b/src/mesa/state_tracker/st_manager.c > @@ -845,6 +845,7 @@ st_manager_get_egl_image_surface(struct st_context *st, > void *eglimg) > return NULL; > > u_surface_default_template(&surf_tmpl, stimg.texture); > + surf_tmpl.format = stimg.format; > surf_tmpl.u.tex.level = stimg.level; > surf_tmpl.u.tex.first_layer = stimg.layer; > surf_tmpl.u.tex.last_layer = stimg.layer; > diff --git a/src/mesa/state_tracker/st_program.c > b/src/mesa/state_tracker/st_program.c > index 03a685c..e6b1017 100644 > --- a/src/mesa/state_tracker/st_program.c > +++ b/src/mesa/state_tracker/st_program.c > @@ -53,6 +53,7 @@ > #include "st_cb_bitmap.h" > #include "st_cb_drawpixels.h" > #include "st_context.h" > +#include "st_tgsi_lower_yuv.h" > #include "st_program.h" > #include "st_mesa_to_tgsi.h" > #include "st_atifs_to_tgsi.h" > @@ -1020,6 +1021,10 @@ st_create_fp_variant(struct st_context *st, > NIR_PASS_V(tgsi.ir.nir, nir_lower_drawpixels, &options); > } > > + if (unlikely(key->lower_nv12 || key->lower_iyuv)) { > + assert(0); // TODO > + } > + > st_finalize_nir(st, &stfp->Base.Base, tgsi.ir.nir); > > variant->driver_shader = pipe->create_fs_state(pipe, &tgsi); Did you forget to drop this hunk? > @@ -1118,6 +1123,19 @@ st_create_fp_variant(struct st_context *st, > fprintf(stderr, "mesa: cannot create a shader for glDrawPixels\n"); > } > > + if (unlikely(key->lower_nv12 || key->lower_iyuv)) { > + const struct tgsi_token *tokens; > + unsigned first_extra_sampler = ffs(~stfp->Base.Base.SamplersUsed) - 1; > + > + /* samplers inserted would conflict, but this should be unpossible: */ > + assert(!(key->bitmap || key->drawpixels)); > + > + tokens = st_tgsi_lower_yuv(tgsi.tokens, first_extra_sampler, > + key->lower_nv12, key->lower_iyuv); > + tgsi_free_tokens(tgsi.tokens); > + tgsi.tokens = tokens; > + } What if SamplersUsed has holes, e.g. SamplersUsed = 1011011b. Marek _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev