[virglrenderer-devel] [PATCH] renderer: add texture view internals (v4)
Gert Wollny
gert.wollny at collabora.com
Tue Jun 26 11:53:22 UTC 2018
Yes, that looks more like it,
Reviewed-by: Gert Wollny
<gert.wollny at collabora.com>
Am Montag, den 25.06.2018, 16:43 +1000 schrieb Dave Airlie:
> From: Dave Airlie <airlied at redhat.com>
>
> This adds the renderer support for exposing texture views.
>
> The change adds support to sampler views and surfaces for the backing
> object to be a separately allocated textureview instead of the actual
> resource. It also adds support for parsing the updated packet where
> we put the sampler view target in the top 8 bits of the format,
> which should be safe as up until now it's always 0.
>
> This doesn't do the final enable of the extension, but it will
> cause us to use views in a few places we didn't before so could have
> some other side effects
>
> v2: check for buffers on surface creation, reword comment
> to better explain if statement.
> v3: fix logic bug (Gert). This uncovered a wierd corner case,
> possibly
> due to how the state tracker allocates textures, but it tries to
> create
> a surface with more layers than there are, I think it then reallocate
> the whole texture object in the guest and it works out in the end,
> this adds check to catch this, and to avoid creating a texture view
> in that case.
> v4: realise the problem with v3 was 3D textures and use
> util_max_layer to fix the logic properly.
> ---
> src/vrend_renderer.c | 96
> +++++++++++++++++++++++++++++++++++++++++++++++-----
> 1 file changed, 88 insertions(+), 8 deletions(-)
>
> diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
> index 00c42ff..95d0dc8 100644
> --- a/src/vrend_renderer.c
> +++ b/src/vrend_renderer.c
> @@ -118,6 +118,7 @@ struct global_renderer_state {
> bool have_polygon_offset_clamp;
> bool have_texture_storage;
> bool have_tessellation;
> + bool have_texture_view;
>
> /* these appeared broken on at least one driver */
> bool use_explicit_locations;
> @@ -230,6 +231,7 @@ struct vrend_sampler_view {
> struct pipe_reference reference;
> GLuint id;
> GLuint format;
> + GLenum target;
> GLuint val0, val1;
> GLuint gl_swizzle_r;
> GLuint gl_swizzle_g;
> @@ -424,6 +426,8 @@ static void vrend_apply_sampler_state(struct
> vrend_context *ctx,
> struct vrend_resource *res,
> uint32_t shader_type,
> int id, int sampler_id,
> uint32_t srgb_decode);
> +static GLenum tgsitargettogltarget(const enum pipe_texture_target
> target, int nr_samples);
> +
> void vrend_update_stencil_state(struct vrend_context *ctx);
>
> static struct vrend_format_table tex_conv_table[VIRGL_FORMAT_MAX];
> @@ -547,6 +551,8 @@ static void __report_gles_missing_func(const char
> *fname, struct vrend_context *
>
> static void vrend_destroy_surface(struct vrend_surface *surf)
> {
> + if (surf->id != surf->texture->id)
> + glDeleteTextures(1, &surf->id);
> vrend_resource_reference(&surf->texture, NULL);
> free(surf);
> }
> @@ -563,6 +569,8 @@ vrend_surface_reference(struct vrend_surface
> **ptr, struct vrend_surface *surf)
>
> static void vrend_destroy_sampler_view(struct vrend_sampler_view
> *samp)
> {
> + if (samp->texture->id != samp->id)
> + glDeleteTextures(1, &samp->id);
> vrend_resource_reference(&samp->texture, NULL);
> free(samp);
> }
> @@ -1212,6 +1220,31 @@ int vrend_create_surface(struct vrend_context
> *ctx,
> surf->format = format;
> surf->val0 = val0;
> surf->val1 = val1;
> + surf->id = res->id;
> +
> + if (vrend_state.have_texture_view && !res->is_buffer) {
> + /* We don't need texture views for buffer objects.
> + * Otherwise we only need a texture view if the
> + * a) formats differ between the surface and base texture
> + * b) we need to map a sub range > 1 layer to a surface,
> + * GL can make a single layer fine without a view, and it
> + * can map the whole texure fine. In those cases we don't
> + * create a texture view.
> + */
> + int first_layer = surf->val1 & 0xffff;
> + int last_layer = (surf->val1 >> 16) & 0xffff;
> +
> + if ((first_layer != last_layer &&
> + (first_layer != 0 || (last_layer != util_max_layer(&res-
> >base, surf->val0)))) ||
> + surf->format != res->base.format) {
> + GLenum internalformat = tex_conv_table[surf-
> >format].internalformat;
> + glGenTextures(1, &surf->id);
> + glTextureView(surf->id, res->target, res->id,
> internalformat,
> + 0, res->base.last_level + 1,
> + first_layer, last_layer - first_layer + 1);
> + }
> + }
> +
> pipe_reference_init(&surf->reference, 1);
>
> vrend_resource_reference(&surf->texture, res);
> @@ -1416,7 +1449,8 @@ int vrend_create_sampler_view(struct
> vrend_context *ctx,
> return ENOMEM;
>
> pipe_reference_init(&view->reference, 1);
> - view->format = format;
> + view->format = format & 0xffffff;
> + view->target = tgsitargettogltarget((format >> 24) & 0xff, res-
> >base.nr_samples);
> view->val0 = val0;
> view->val1 = val1;
> view->cur_base = -1;
> @@ -1429,6 +1463,49 @@ int vrend_create_sampler_view(struct
> vrend_context *ctx,
>
> vrend_resource_reference(&view->texture, res);
>
> + view->id = view->texture->id;
> + if (!view->target)
> + view->target = view->texture->target;
> +
> + if (vrend_state.have_texture_view && !view->texture-
> >is_buffer) {
> + enum pipe_format format;
> + bool needs_view = false;
> +
> + /*
> + * Need to use a texture view if the gallium
> + * view target is different than the underlying
> + * texture target.
> + */
> + if (view->target != view->texture->target)
> + needs_view = true;
> +
> + /*
> + * If the formats are different and this isn't
> + * a DS texture a view is required.
> + * DS are special as they use different gallium
> + * formats for DS views into a combined resource.
> + * GL texture views can't be use for this, stencil
> + * texturing is used instead. For DS formats
> + * aways program the underlying DS format as a
> + * view could be required for layers.
> + */
> + format = view->format;
> + if (util_format_is_depth_or_stencil(view->texture-
> >base.format))
> + format = view->texture->base.format;
> + else if (view->format != view->texture->base.format)
> + needs_view = true;
> + if (needs_view) {
> + glGenTextures(1, &view->id);
> + GLenum internalformat =
> tex_conv_table[format].internalformat;
> + unsigned base_layer = view->val0 & 0xffff;
> + unsigned max_layer = (view->val0 >> 16) & 0xffff;
> + view->cur_base = view->val1 & 0xff;
> + view->cur_max = (view->val1 >> 8) & 0xff;
> + glTextureView(view->id, view->target, view->texture->id,
> internalformat,
> + view->cur_base, (view->cur_max - view-
> >cur_base) + 1,
> + base_layer, max_layer - base_layer + 1);
> + }
> + }
> view->srgb_decode = GL_DECODE_EXT;
> if (view->format != view->texture->base.format) {
> if (util_format_is_srgb(view->texture->base.format) &&
> @@ -1567,8 +1644,8 @@ static void vrend_hw_set_zsurf_texture(struct
> vrend_context *ctx)
> if (!surf->texture)
> return;
>
> - vrend_fb_bind_texture(surf->texture, 0, surf->val0,
> - first_layer != last_layer ? 0xffffffff :
> first_layer);
> + vrend_fb_bind_texture_id(surf->texture, surf->id, 0, surf-
> >val0,
> + first_layer != last_layer ?
> 0xffffffff : first_layer);
> }
> }
>
> @@ -1585,8 +1662,8 @@ static void vrend_hw_set_color_surface(struct
> vrend_context *ctx, int index)
> uint32_t first_layer = ctx->sub->surf[index]->val1 & 0xffff;
> uint32_t last_layer = (ctx->sub->surf[index]->val1 >> 16) &
> 0xffff;
>
> - vrend_fb_bind_texture(surf->texture, index, surf->val0,
> - first_layer != last_layer ? 0xffffffff :
> first_layer);
> + vrend_fb_bind_texture_id(surf->texture, surf->id, index, surf-
> >val0,
> + first_layer != last_layer ?
> 0xffffffff : first_layer);
> }
> }
>
> @@ -2084,7 +2161,7 @@ void vrend_set_single_sampler_view(struct
> vrend_context *ctx,
> return;
> }
> if (!view->texture->is_buffer) {
> - glBindTexture(view->texture->target, view->texture->id);
> + glBindTexture(view->target, view->id);
>
> if (util_format_is_depth_or_stencil(view->format)) {
> if (vrend_state.use_core_profile == false) {
> @@ -2985,13 +3062,13 @@ static void
> vrend_draw_bind_samplers_shader(struct vrend_context *ctx,
> if (tview->texture) {
> GLuint id;
> struct vrend_resource *texture = tview->texture;
> - GLenum target = texture->target;
> + GLenum target = tview->target;
>
> if (texture->is_buffer) {
> id = texture->tbo_tex_id;
> target = GL_TEXTURE_BUFFER;
> } else
> - id = texture->id;
> + id = tview->id;
>
> glBindTexture(target, id);
> if (ctx->sub->views[shader_type].old_ids[i] != id || ctx-
> >sub->sampler_state_dirty) {
> @@ -4444,6 +4521,9 @@ int vrend_renderer_init(struct vrend_if_cbs
> *cbs, uint32_t flags)
> if (gl_ver >= 42 ||
> epoxy_has_gl_extension("GL_ARB_texture_storage"))
> vrend_state.have_texture_storage = true;
>
> + if (gl_ver >= 43 ||
> epoxy_has_gl_extension("GL_ARB_texture_view"))
> + vrend_state.have_texture_view = true;
> +
> if (gl_ver >= 46 ||
> epoxy_has_gl_extension("GL_ARB_polygon_offset_clamp"))
> vrend_state.have_polygon_offset_clamp = true;
>
More information about the virglrenderer-devel
mailing list