From 55ad59d2b72d6d6e38bd0a54586b713a7a93bb10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Fri, 27 Jan 2017 00:12:37 +0100 Subject: [PATCH] gallium: set pipe_context uploaders in drivers (v3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Notes: - make sure the default size is large enough to handle all state trackers - pipe wrappers don't receive transfer calls from stream_uploader, because pipe_context::stream_uploader points directly to the underlying driver's stream_uploader (to keep it simple for now) v2: add error handling to nv50, nvc0, noop v3: set const_uploader Reviewed-by: Nicolai Hähnle Tested-by: Edmondo Tommasina (v1) Tested-by: Charmaine Lee --- src/gallium/drivers/ddebug/dd_context.c | 2 ++ src/gallium/drivers/etnaviv/etnaviv_context.c | 8 ++++++++ .../drivers/freedreno/freedreno_context.c | 9 +++++++++ src/gallium/drivers/i915/i915_context.c | 6 ++++++ src/gallium/drivers/llvmpipe/lp_context.c | 9 +++++++++ src/gallium/drivers/noop/noop_pipe.c | 13 +++++++++++++ .../drivers/nouveau/nv30/nv30_context.c | 11 +++++++++++ .../drivers/nouveau/nv50/nv50_context.c | 11 +++++++++++ .../drivers/nouveau/nvc0/nvc0_context.c | 10 ++++++++++ src/gallium/drivers/r300/r300_context.c | 4 +++- src/gallium/drivers/radeon/r600_pipe_common.c | 2 ++ src/gallium/drivers/rbug/rbug_context.c | 2 ++ src/gallium/drivers/softpipe/sp_context.c | 8 ++++++++ src/gallium/drivers/svga/svga_context.c | 18 ++++++++++++++++++ src/gallium/drivers/swr/swr_context.cpp | 9 +++++++++ src/gallium/drivers/trace/tr_context.c | 2 ++ src/gallium/drivers/vc4/vc4_context.c | 11 ++++++----- src/gallium/drivers/virgl/virgl_context.c | 2 ++ 18 files changed, 131 insertions(+), 6 deletions(-) diff --git a/src/gallium/drivers/ddebug/dd_context.c b/src/gallium/drivers/ddebug/dd_context.c index 0b1dfbbc57c..ba47b734bba 100644 --- a/src/gallium/drivers/ddebug/dd_context.c +++ b/src/gallium/drivers/ddebug/dd_context.c @@ -763,6 +763,8 @@ dd_context_create(struct dd_screen *dscreen, struct pipe_context *pipe) dctx->pipe = pipe; dctx->base.priv = pipe->priv; /* expose wrapped priv data */ dctx->base.screen = &dscreen->base; + dctx->base.stream_uploader = pipe->stream_uploader; + dctx->base.const_uploader = pipe->const_uploader; dctx->base.destroy = dd_context_destroy; diff --git a/src/gallium/drivers/etnaviv/etnaviv_context.c b/src/gallium/drivers/etnaviv/etnaviv_context.c index ce2d8719e45..62297a05047 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_context.c +++ b/src/gallium/drivers/etnaviv/etnaviv_context.c @@ -49,6 +49,7 @@ #include "util/u_blitter.h" #include "util/u_memory.h" #include "util/u_prim.h" +#include "util/u_upload_mgr.h" #include "hw/common.xml.h" @@ -63,6 +64,9 @@ etna_context_destroy(struct pipe_context *pctx) if (ctx->blitter) util_blitter_destroy(ctx->blitter); + if (pctx->stream_uploader) + u_upload_destroy(pctx->stream_uploader); + if (ctx->stream) etna_cmd_stream_del(ctx->stream); @@ -276,6 +280,10 @@ etna_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) pctx = &ctx->base; pctx->priv = ctx; pctx->screen = pscreen; + pctx->stream_uploader = u_upload_create_default(pctx); + if (!pctx->stream_uploader) + goto fail; + pctx->const_uploader = pctx->stream_uploader; /* context ctxate setup */ ctx->specs = screen->specs; diff --git a/src/gallium/drivers/freedreno/freedreno_context.c b/src/gallium/drivers/freedreno/freedreno_context.c index 348cc60e9ca..4d8c4251a8b 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.c +++ b/src/gallium/drivers/freedreno/freedreno_context.c @@ -37,6 +37,7 @@ #include "freedreno_query.h" #include "freedreno_query_hw.h" #include "freedreno_util.h" +#include "util/u_upload_mgr.h" static void fd_context_flush(struct pipe_context *pctx, struct pipe_fence_handle **fence, @@ -125,6 +126,9 @@ fd_context_destroy(struct pipe_context *pctx) if (ctx->blitter) util_blitter_destroy(ctx->blitter); + if (pctx->stream_uploader) + u_upload_destroy(pctx->stream_uploader); + if (ctx->clear_rs_state) pctx->delete_rasterizer_state(pctx, ctx->clear_rs_state); @@ -269,6 +273,11 @@ fd_context_init(struct fd_context *ctx, struct pipe_screen *pscreen, pctx->create_fence_fd = fd_create_fence_fd; pctx->fence_server_sync = fd_fence_server_sync; + pctx->stream_uploader = u_upload_create_default(pctx); + if (!pctx->stream_uploader) + goto fail; + pctx->const_uploader = pctx->stream_uploader; + /* TODO what about compute? Ideally it creates it's own independent * batches per compute job (since it isn't using tiling, so no point * in getting involved with the re-ordering madness).. diff --git a/src/gallium/drivers/i915/i915_context.c b/src/gallium/drivers/i915/i915_context.c index f3324dbc229..6664cfc3dfe 100644 --- a/src/gallium/drivers/i915/i915_context.c +++ b/src/gallium/drivers/i915/i915_context.c @@ -37,6 +37,7 @@ #include "pipe/p_defines.h" #include "util/u_inlines.h" #include "util/u_memory.h" +#include "util/u_upload_mgr.h" #include "pipe/p_screen.h" @@ -137,6 +138,9 @@ static void i915_destroy(struct pipe_context *pipe) draw_destroy(i915->draw); + if (i915->base.stream_uploader) + u_upload_destroy(i915->base.stream_uploader); + if(i915->batch) i915->iws->batchbuffer_destroy(i915->batch); @@ -166,6 +170,8 @@ i915_create_context(struct pipe_screen *screen, void *priv, unsigned flags) i915->iws = i915_screen(screen)->iws; i915->base.screen = screen; i915->base.priv = priv; + i915->base.stream_uploader = u_upload_create_default(&i915->base); + i915->base.const_uploader = i915->base.stream_uploader; i915->base.destroy = i915_destroy; diff --git a/src/gallium/drivers/llvmpipe/lp_context.c b/src/gallium/drivers/llvmpipe/lp_context.c index 84912c6f114..9a1a7b9ad5f 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.c +++ b/src/gallium/drivers/llvmpipe/lp_context.c @@ -37,6 +37,7 @@ #include "util/u_math.h" #include "util/u_memory.h" #include "util/simple_list.h" +#include "util/u_upload_mgr.h" #include "lp_clear.h" #include "lp_context.h" #include "lp_flush.h" @@ -62,6 +63,9 @@ static void llvmpipe_destroy( struct pipe_context *pipe ) util_blitter_destroy(llvmpipe->blitter); } + if (llvmpipe->pipe.stream_uploader) + u_upload_destroy(llvmpipe->pipe.stream_uploader); + /* This will also destroy llvmpipe->setup: */ if (llvmpipe->draw) @@ -195,6 +199,11 @@ llvmpipe_create_context(struct pipe_screen *screen, void *priv, if (!llvmpipe->setup) goto fail; + llvmpipe->pipe.stream_uploader = u_upload_create_default(&llvmpipe->pipe); + if (!llvmpipe->pipe.stream_uploader) + goto fail; + llvmpipe->pipe.const_uploader = llvmpipe->pipe.stream_uploader; + llvmpipe->blitter = util_blitter_create(&llvmpipe->pipe); if (!llvmpipe->blitter) { goto fail; diff --git a/src/gallium/drivers/noop/noop_pipe.c b/src/gallium/drivers/noop/noop_pipe.c index 301301966ce..db2375e2e5d 100644 --- a/src/gallium/drivers/noop/noop_pipe.c +++ b/src/gallium/drivers/noop/noop_pipe.c @@ -29,6 +29,7 @@ #include "util/u_memory.h" #include "util/u_inlines.h" #include "util/u_format.h" +#include "util/u_upload_mgr.h" #include "noop_public.h" DEBUG_GET_ONCE_BOOL_OPTION(noop, "GALLIUM_NOOP", FALSE) @@ -289,6 +290,9 @@ static void noop_flush(struct pipe_context *ctx, static void noop_destroy_context(struct pipe_context *ctx) { + if (ctx->stream_uploader) + u_upload_destroy(ctx->stream_uploader); + FREE(ctx); } @@ -310,8 +314,17 @@ static struct pipe_context *noop_create_context(struct pipe_screen *screen, if (!ctx) return NULL; + ctx->screen = screen; ctx->priv = priv; + + ctx->stream_uploader = u_upload_create_default(ctx); + if (!ctx->stream_uploader) { + FREE(ctx); + return NULL; + } + ctx->const_uploader = ctx->stream_uploader; + ctx->destroy = noop_destroy_context; ctx->flush = noop_flush; ctx->clear = noop_clear; diff --git a/src/gallium/drivers/nouveau/nv30/nv30_context.c b/src/gallium/drivers/nouveau/nv30/nv30_context.c index 3ed088912e2..716d2bbe4c1 100644 --- a/src/gallium/drivers/nouveau/nv30/nv30_context.c +++ b/src/gallium/drivers/nouveau/nv30/nv30_context.c @@ -24,6 +24,7 @@ */ #include "draw/draw_context.h" +#include "util/u_upload_mgr.h" #include "nv_object.xml.h" #include "nv30/nv30-40_3d.xml.h" @@ -165,6 +166,9 @@ nv30_context_destroy(struct pipe_context *pipe) if (nv30->draw) draw_destroy(nv30->draw); + if (nv30->base.pipe.stream_uploader) + u_upload_destroy(nv30->base.pipe.stream_uploader); + if (nv30->blit_vp) nouveau_heap_free(&nv30->blit_vp); @@ -205,6 +209,13 @@ nv30_context_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) nv30->base.screen = &screen->base; nv30->base.copy_data = nv30_transfer_copy_data; + nv30->base.pipe.stream_uploader = u_upload_create_default(&nv30->base.pipe); + if (!nv30->base.pipe.stream_uploader) { + nv30_context_destroy(pipe); + return NULL; + } + nv30->base.pipe.const_uploader = nv30->base.pipe.stream_uploader; + pipe = &nv30->base.pipe; pipe->screen = pscreen; pipe->priv = priv; diff --git a/src/gallium/drivers/nouveau/nv50/nv50_context.c b/src/gallium/drivers/nouveau/nv50/nv50_context.c index ece7da9c5b4..bf768bc6db5 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_context.c +++ b/src/gallium/drivers/nouveau/nv50/nv50_context.c @@ -22,6 +22,7 @@ #include "pipe/p_defines.h" #include "util/u_framebuffer.h" +#include "util/u_upload_mgr.h" #include "nv50/nv50_context.h" #include "nv50/nv50_screen.h" @@ -176,6 +177,10 @@ nv50_destroy(struct pipe_context *pipe) /* Save off the state in case another context gets created */ nv50->screen->save_state = nv50->state; } + + if (nv50->base.pipe.stream_uploader) + u_upload_destroy(nv50->base.pipe.stream_uploader); + nouveau_pushbuf_bufctx(nv50->base.pushbuf, NULL); nouveau_pushbuf_kick(nv50->base.pushbuf, nv50->base.pushbuf->channel); @@ -315,6 +320,10 @@ nv50_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) nv50->screen = screen; pipe->screen = pscreen; pipe->priv = priv; + pipe->stream_uploader = u_upload_create_default(pipe); + if (!pipe->stream_uploader) + goto out_err; + pipe->const_uploader = pipe->stream_uploader; pipe->destroy = nv50_destroy; @@ -387,6 +396,8 @@ nv50_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) return pipe; out_err: + if (pipe->stream_uploader) + u_upload_destroy(pipe->stream_uploader); if (nv50->bufctx_3d) nouveau_bufctx_del(&nv50->bufctx_3d); if (nv50->bufctx_cp) diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c index 8f2b974b34a..d0f4da303bb 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_context.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_context.c @@ -22,6 +22,7 @@ #include "pipe/p_defines.h" #include "util/u_framebuffer.h" +#include "util/u_upload_mgr.h" #include "nvc0/nvc0_context.h" #include "nvc0/nvc0_screen.h" @@ -199,6 +200,9 @@ nvc0_destroy(struct pipe_context *pipe) nvc0->screen->save_state.tfb = NULL; } + if (nvc0->base.pipe.stream_uploader) + u_upload_destroy(nvc0->base.pipe.stream_uploader); + /* Unset bufctx, we don't want to revalidate any resources after the flush. * Other contexts will always set their bufctx again on action calls. */ @@ -386,6 +390,10 @@ nvc0_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) pipe->screen = pscreen; pipe->priv = priv; + pipe->stream_uploader = u_upload_create_default(pipe); + if (!pipe->stream_uploader) + goto out_err; + pipe->const_uploader = pipe->stream_uploader; pipe->destroy = nvc0_destroy; @@ -472,6 +480,8 @@ nvc0_create(struct pipe_screen *pscreen, void *priv, unsigned ctxflags) out_err: if (nvc0) { + if (pipe->stream_uploader) + u_upload_destroy(pipe->stream_uploader); if (nvc0->bufctx_3d) nouveau_bufctx_del(&nvc0->bufctx_3d); if (nvc0->bufctx_cp) diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index b914cdb919b..02af5d7f2f8 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -424,8 +424,10 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, r300->context.create_video_codec = vl_create_decoder; r300->context.create_video_buffer = vl_video_buffer_create; - r300->uploader = u_upload_create(&r300->context, 256 * 1024, + r300->uploader = u_upload_create(&r300->context, 1024 * 1024, PIPE_BIND_CUSTOM, PIPE_USAGE_STREAM); + r300->context.stream_uploader = r300->uploader; + r300->context.const_uploader = r300->uploader; r300->blitter = util_blitter_create(&r300->context); if (r300->blitter == NULL) diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c b/src/gallium/drivers/radeon/r600_pipe_common.c index 95a6a486a3d..732f5c348c1 100644 --- a/src/gallium/drivers/radeon/r600_pipe_common.c +++ b/src/gallium/drivers/radeon/r600_pipe_common.c @@ -606,6 +606,8 @@ bool r600_common_context_init(struct r600_common_context *rctx, PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_STREAM); if (!rctx->uploader) return false; + rctx->b.stream_uploader = rctx->uploader; + rctx->b.const_uploader = rctx->uploader; rctx->ctx = rctx->ws->ctx_create(rctx->ws); if (!rctx->ctx) diff --git a/src/gallium/drivers/rbug/rbug_context.c b/src/gallium/drivers/rbug/rbug_context.c index b08acfaf8c1..1dd0f6d42d2 100644 --- a/src/gallium/drivers/rbug/rbug_context.c +++ b/src/gallium/drivers/rbug/rbug_context.c @@ -1212,6 +1212,8 @@ rbug_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) rb_pipe->base.screen = _screen; rb_pipe->base.priv = pipe->priv; /* expose wrapped data */ rb_pipe->base.draw = NULL; + rb_pipe->base.stream_uploader = pipe->stream_uploader; + rb_pipe->base.const_uploader = pipe->const_uploader; rb_pipe->base.destroy = rbug_destroy; rb_pipe->base.draw_vbo = rbug_draw_vbo; diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c index 323f74ff3bd..05973012504 100644 --- a/src/gallium/drivers/softpipe/sp_context.c +++ b/src/gallium/drivers/softpipe/sp_context.c @@ -37,6 +37,7 @@ #include "util/u_memory.h" #include "util/u_pstipple.h" #include "util/u_inlines.h" +#include "util/u_upload_mgr.h" #include "tgsi/tgsi_exec.h" #include "sp_buffer.h" #include "sp_clear.h" @@ -86,6 +87,9 @@ softpipe_destroy( struct pipe_context *pipe ) if (softpipe->quad.pstipple) softpipe->quad.pstipple->destroy( softpipe->quad.pstipple ); + if (softpipe->pipe.stream_uploader) + u_upload_destroy(softpipe->pipe.stream_uploader); + for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { sp_destroy_tile_cache(softpipe->cbuf_cache[i]); pipe_surface_reference(&softpipe->framebuffer.cbufs[i], NULL); @@ -267,6 +271,10 @@ softpipe_create_context(struct pipe_screen *screen, softpipe->quad.blend = sp_quad_blend_stage(softpipe); softpipe->quad.pstipple = sp_quad_polygon_stipple_stage(softpipe); + softpipe->pipe.stream_uploader = u_upload_create_default(&softpipe->pipe); + if (!softpipe->pipe.stream_uploader) + goto fail; + softpipe->pipe.const_uploader = softpipe->pipe.stream_uploader; /* * Create drawing context and plug our rendering stage into it. diff --git a/src/gallium/drivers/svga/svga_context.c b/src/gallium/drivers/svga/svga_context.c index d3f18014135..ec86073ccc9 100644 --- a/src/gallium/drivers/svga/svga_context.c +++ b/src/gallium/drivers/svga/svga_context.c @@ -103,6 +103,8 @@ svga_destroy(struct pipe_context *pipe) util_bitmask_destroy(svga->stream_output_id_bm); util_bitmask_destroy(svga->query_id_bm); u_upload_destroy(svga->const0_upload); + u_upload_destroy(svga->pipe.stream_uploader); + u_upload_destroy(svga->pipe.const_uploader); svga_texture_transfer_map_upload_destroy(svga); /* free user's constant buffers */ @@ -132,6 +134,18 @@ svga_context_create(struct pipe_screen *screen, void *priv, unsigned flags) svga->pipe.screen = screen; svga->pipe.priv = priv; svga->pipe.destroy = svga_destroy; + svga->pipe.stream_uploader = u_upload_create(&svga->pipe, 1024 * 1024, + PIPE_BIND_VERTEX_BUFFER | + PIPE_BIND_INDEX_BUFFER, + PIPE_USAGE_STREAM); + if (!svga->pipe.stream_uploader) + goto cleanup; + + svga->pipe.const_uploader = u_upload_create(&svga->pipe, 128 * 1024, + PIPE_BIND_CONSTANT_BUFFER, + PIPE_USAGE_STREAM); + if (!svga->pipe.const_uploader) + goto cleanup; svga->swc = svgascreen->sws->context_create(svgascreen->sws); if (!svga->swc) @@ -283,6 +297,10 @@ cleanup: if (svga->const0_upload) u_upload_destroy(svga->const0_upload); + if (svga->pipe.const_uploader) + u_upload_destroy(svga->pipe.const_uploader); + if (svga->pipe.stream_uploader) + u_upload_destroy(svga->pipe.stream_uploader); svga_texture_transfer_map_upload_destroy(svga); if (svga->hwtnl) svga_hwtnl_destroy(svga->hwtnl); diff --git a/src/gallium/drivers/swr/swr_context.cpp b/src/gallium/drivers/swr/swr_context.cpp index 89330857ae0..2e37bacfac6 100644 --- a/src/gallium/drivers/swr/swr_context.cpp +++ b/src/gallium/drivers/swr/swr_context.cpp @@ -33,6 +33,7 @@ #include "util/u_inlines.h" #include "util/u_format.h" #include "util/u_atomic.h" +#include "util/u_upload_mgr.h" extern "C" { #include "util/u_transfer.h" @@ -369,6 +370,9 @@ swr_destroy(struct pipe_context *pipe) pipe_sampler_view_reference(&ctx->sampler_views[PIPE_SHADER_VERTEX][i], NULL); } + if (ctx->pipe.stream_uploader) + u_upload_destroy(ctx->pipe.stream_uploader); + /* Idle core after destroying buffer resources, but before deleting * context. Destroying resources has potentially called StoreTiles.*/ SwrWaitForIdle(ctx->swrContext); @@ -493,6 +497,11 @@ swr_create_context(struct pipe_screen *p_screen, void *priv, unsigned flags) swr_draw_init(&ctx->pipe); swr_query_init(&ctx->pipe); + ctx->pipe.stream_uploader = u_upload_create_default(&ctx->pipe); + if (!ctx->pipe.stream_uploader) + goto fail; + ctx->pipe.const_uploader = ctx->pipe.stream_uploader; + ctx->pipe.blit = swr_blit; ctx->blitter = util_blitter_create(&ctx->pipe); if (!ctx->blitter) diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c index de03e29b4e3..f5939b1126c 100644 --- a/src/gallium/drivers/trace/tr_context.c +++ b/src/gallium/drivers/trace/tr_context.c @@ -1851,6 +1851,8 @@ trace_context_create(struct trace_screen *tr_scr, tr_ctx->base.priv = pipe->priv; /* expose wrapped priv data */ tr_ctx->base.screen = &tr_scr->base; + tr_ctx->base.stream_uploader = pipe->stream_uploader; + tr_ctx->base.const_uploader = pipe->const_uploader; tr_ctx->base.destroy = trace_context_destroy; diff --git a/src/gallium/drivers/vc4/vc4_context.c b/src/gallium/drivers/vc4/vc4_context.c index 974df8a1da2..401c160fcc2 100644 --- a/src/gallium/drivers/vc4/vc4_context.c +++ b/src/gallium/drivers/vc4/vc4_context.c @@ -144,7 +144,12 @@ vc4_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) vc4->fd = screen->fd; slab_create_child(&vc4->transfer_pool, &screen->transfer_pool); - vc4->blitter = util_blitter_create(pctx); + + vc4->uploader = u_upload_create_default(&vc4->base); + vc4->base.stream_uploader = vc4->uploader; + vc4->base.const_uploader = vc4->uploader; + + vc4->blitter = util_blitter_create(pctx); if (!vc4->blitter) goto fail; @@ -153,10 +158,6 @@ vc4_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags) if (!vc4->primconvert) goto fail; - vc4->uploader = u_upload_create(pctx, 16 * 1024, - PIPE_BIND_INDEX_BUFFER, - PIPE_USAGE_STREAM); - vc4_debug |= saved_shaderdb_flag; vc4->sample_mask = (1 << VC4_MAX_SAMPLES) - 1; diff --git a/src/gallium/drivers/virgl/virgl_context.c b/src/gallium/drivers/virgl/virgl_context.c index bda9515d9b6..2ee89d7ff4b 100644 --- a/src/gallium/drivers/virgl/virgl_context.c +++ b/src/gallium/drivers/virgl/virgl_context.c @@ -950,6 +950,8 @@ struct pipe_context *virgl_context_create(struct pipe_screen *pscreen, PIPE_BIND_INDEX_BUFFER, PIPE_USAGE_STREAM); if (!vctx->uploader) goto fail; + vctx->base.stream_uploader = vctx->uploader; + vctx->base.const_uploader = vctx->uploader; vctx->hw_sub_ctx_id = rs->sub_ctx_id++; virgl_encoder_create_sub_ctx(vctx, vctx->hw_sub_ctx_id);