From: Nicolai Hähnle <nicolai.haeh...@amd.com> Use instancing to generate two triangles for each destination layer and use a geometry shader to route the layer index. --- src/mesa/state_tracker/st_cb_texture.c | 145 +++++++++++++++++++++++++++------ src/mesa/state_tracker/st_context.h | 2 + 2 files changed, 122 insertions(+), 25 deletions(-)
diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index c3aadb5..7804786 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -698,17 +698,9 @@ st_init_pbo_upload(struct st_context *st) st->pbo_upload.rgba_only = screen->get_param(screen, PIPE_CAP_BUFFER_SAMPLER_VIEW_RGBA_ONLY); - - /* Create the vertex shader */ - { - unsigned semantic_names[] = { TGSI_SEMANTIC_POSITION }; - unsigned semantic_indexes[] = { 0 }; - - st->pbo_upload.vs = util_make_vertex_passthrough_shader(pipe, 1, - semantic_names, - semantic_indexes, - FALSE); - } + st->pbo_upload.upload_layers = + screen->get_param(screen, PIPE_CAP_TGSI_INSTANCEID) && + screen->get_param(screen, PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES) >= 3; /* Blend state */ memset(&st->pbo_upload.blend, 0, sizeof(struct pipe_blend_state)); @@ -1113,7 +1105,82 @@ reinterpret_formats(enum pipe_format *src_format, enum pipe_format *dst_format) } static void * -create_pbo_upload_shader(struct pipe_context *pipe) +create_pbo_upload_vs(struct st_context *st) +{ + struct ureg_program *ureg; + struct ureg_src in_pos; + struct ureg_src in_instanceid; + struct ureg_dst out_pos; + + ureg = ureg_create(TGSI_PROCESSOR_VERTEX); + + in_pos = ureg_DECL_vs_input(ureg, TGSI_SEMANTIC_POSITION); + + if (st->pbo_upload.upload_layers) + in_instanceid = ureg_DECL_system_value(ureg, TGSI_SEMANTIC_INSTANCEID, 0); + + out_pos = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); + + /* out_pos = in_pos */ + ureg_MOV(ureg, out_pos, in_pos); + + if (st->pbo_upload.upload_layers) { + /* out_pos.z = i2f(gl_InstanceID) */ + ureg_I2F(ureg, ureg_writemask(out_pos, TGSI_WRITEMASK_Z), + ureg_scalar(in_instanceid, TGSI_SWIZZLE_X)); + } + + ureg_END(ureg); + + return ureg_create_shader_and_destroy(ureg, st->pipe); +} + +static void * +create_pbo_upload_gs(struct st_context *st) +{ + static const int zero = 0; + struct ureg_program *ureg; + struct ureg_dst out_pos; + struct ureg_dst out_layer; + struct ureg_src in_pos; + struct ureg_src imm; + unsigned i; + + ureg = ureg_create(TGSI_PROCESSOR_GEOMETRY); + if (!ureg) + return NULL; + + ureg_property(ureg, TGSI_PROPERTY_GS_INPUT_PRIM, PIPE_PRIM_TRIANGLES); + ureg_property(ureg, TGSI_PROPERTY_GS_OUTPUT_PRIM, PIPE_PRIM_TRIANGLE_STRIP); + ureg_property(ureg, TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES, 3); + + out_pos = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0); + out_layer = ureg_DECL_output(ureg, TGSI_SEMANTIC_LAYER, 0); + + in_pos = ureg_DECL_input(ureg, TGSI_SEMANTIC_POSITION, 0, 0, 1); + + imm = ureg_DECL_immediate_int(ureg, &zero, 1); + + for (i = 0; i < 3; ++i) { + struct ureg_src in_pos_vertex = ureg_src_dimension(in_pos, i); + + /* out_pos = in_pos[i] */ + ureg_MOV(ureg, out_pos, in_pos_vertex); + + /* out_layer.x = f2i(in_pos[i].z) */ + ureg_F2I(ureg, ureg_writemask(out_layer, TGSI_WRITEMASK_X), + ureg_scalar(in_pos_vertex, TGSI_SWIZZLE_Z)); + + ureg_EMIT(ureg, ureg_scalar(imm, TGSI_SWIZZLE_X)); + } + + ureg_END(ureg); + + return ureg_create_shader_and_destroy(ureg, st->pipe); +} + +static void * +create_pbo_upload_fs(struct st_context *st) { struct ureg_program *ureg; struct ureg_dst out; @@ -1122,7 +1189,10 @@ create_pbo_upload_shader(struct pipe_context *pipe) struct ureg_src const0; struct ureg_dst temp0; - ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT); + ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT); + if (!ureg) + return NULL; + out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0); sampler = ureg_DECL_sampler(ureg, 0); pos = ureg_DECL_fs_input(ureg, TGSI_SEMANTIC_POSITION, 0, @@ -1130,15 +1200,15 @@ create_pbo_upload_shader(struct pipe_context *pipe) const0 = ureg_DECL_constant(ureg, 0); temp0 = ureg_DECL_temporary(ureg); - /* Note: const0 = [ -xoffset, -yoffset, stride, 0 ] */ + /* Note: const0 = [ -xoffset, -yoffset, stride, stride * image_height ] */ ureg_MOV(ureg, temp0, pos); - /* temp0.xy = f2i(temp0.xy) */ - ureg_F2I(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_XY), + /* temp0.xyz = f2i(temp0.xyz) */ + ureg_F2I(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_XYZ), ureg_swizzle(ureg_src(temp0), TGSI_SWIZZLE_X, TGSI_SWIZZLE_Y, - TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Y)); + TGSI_SWIZZLE_Z, TGSI_SWIZZLE_Z)); /* temp0.xy = temp0.xy + const0.xy */ ureg_UADD(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_XY), @@ -1155,6 +1225,14 @@ create_pbo_upload_shader(struct pipe_context *pipe) ureg_scalar(ureg_src(temp0), TGSI_SWIZZLE_Y), ureg_scalar(ureg_src(temp0), TGSI_SWIZZLE_X)); + if (st->pbo_upload.upload_layers) { + /* temp0.x = const0.w * temp0.z + temp0.x */ + ureg_UMAD(ureg, ureg_writemask(temp0, TGSI_WRITEMASK_X), + ureg_scalar(const0, TGSI_SWIZZLE_W), + ureg_scalar(ureg_src(temp0), TGSI_SWIZZLE_Z), + ureg_scalar(ureg_src(temp0), TGSI_SWIZZLE_X)); + } + /* out = txf(sampler, temp0.x) */ ureg_TXF(ureg, out, TGSI_TEXTURE_BUFFER, ureg_scalar(ureg_src(temp0), TGSI_SWIZZLE_X), @@ -1164,7 +1242,7 @@ create_pbo_upload_shader(struct pipe_context *pipe) ureg_END(ureg); - return ureg_create_shader_and_destroy(ureg, pipe); + return ureg_create_shader_and_destroy(ureg, st->pipe); } static bool @@ -1189,8 +1267,20 @@ try_pbo_upload_common(struct gl_context *ctx, return false; /* Create the shaders */ + if (!st->pbo_upload.vs) { + st->pbo_upload.vs = create_pbo_upload_vs(st); + if (!st->pbo_upload.vs) + return false; + } + + if (depth != 1 && !st->pbo_upload.gs) { + st->pbo_upload.gs = create_pbo_upload_gs(st); + if (!st->pbo_upload.gs) + return false; + } + if (!st->pbo_upload.fs) { - st->pbo_upload.fs = create_pbo_upload_shader(pipe); + st->pbo_upload.fs = create_pbo_upload_fs(st); if (!st->pbo_upload.fs) return false; } @@ -1315,13 +1405,13 @@ try_pbo_upload_common(struct gl_context *ctx, int32_t xoffset; int32_t yoffset; int32_t stride; - int32_t pad; + int32_t image_size; } constants; constants.xoffset = -xoffset; constants.yoffset = -yoffset; constants.stride = stride; - constants.pad = 0; + constants.image_size = stride * image_height; if (st->constbuf_uploader) { cb.buffer = NULL; @@ -1346,7 +1436,8 @@ try_pbo_upload_common(struct gl_context *ctx, cso_set_vertex_shader_handle(st->cso_context, st->pbo_upload.vs); cso_save_geometry_shader(st->cso_context); - cso_set_geometry_shader_handle(st->cso_context, NULL); + cso_set_geometry_shader_handle(st->cso_context, + depth != 1 ? st->pbo_upload.gs : NULL); cso_save_tessctrl_shader(st->cso_context); cso_set_tessctrl_shader_handle(st->cso_context, NULL); @@ -1361,7 +1452,12 @@ try_pbo_upload_common(struct gl_context *ctx, cso_save_stream_outputs(st->cso_context); cso_set_stream_outputs(st->cso_context, 0, NULL, 0); - cso_draw_arrays(st->cso_context, PIPE_PRIM_TRIANGLE_STRIP, 0, 4); + if (depth == 1) { + cso_draw_arrays(st->cso_context, PIPE_PRIM_TRIANGLE_STRIP, 0, 4); + } else { + cso_draw_arrays_instanced(st->cso_context, PIPE_PRIM_TRIANGLE_STRIP, + 0, 4, 0, depth); + } cso_restore_fragment_sampler_views(st->cso_context); cso_restore_framebuffer(st->cso_context); @@ -1422,8 +1518,7 @@ try_pbo_upload(struct gl_context *ctx, GLuint dims, image_height = unpack->ImageHeight > 0 ? unpack->ImageHeight : height; } - /* XXX We only support updating a single layer */ - if (depth != 1) + if (depth != 1 && !st->pbo_upload.upload_layers) return false; /* Choose the source format. Initially, we do so without checking driver diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index 4baa707..c73c206 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -207,8 +207,10 @@ struct st_context struct pipe_rasterizer_state raster; struct pipe_blend_state blend; void *vs; + void *gs; void *fs; bool rgba_only; + bool upload_layers; } pbo_upload; /** used for anything using util_draw_vertex_buffer */ -- 2.5.0 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev