From 1ba46bbb4c99caa7e297f2ec6717e962765275cb Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Sun, 21 Apr 2013 19:39:03 +0200 Subject: gallium/u_blitter: implement buffer clearing Although this might be useful for ARB_clear_buffer_object, I need it for initializating resources in r600g. Reviewed-by: Alex Deucher Reviewed-by: Brian Paul v2: comment cleanups NOTE: This is a candidate for the 9.1 branch. --- src/gallium/auxiliary/util/u_blitter.c | 87 +++++++++++++++++++++++++++++++--- 1 file changed, 80 insertions(+), 7 deletions(-) (limited to 'src/gallium/auxiliary/util/u_blitter.c') diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c index 2a4a13e9ff4..85e1e979120 100644 --- a/src/gallium/auxiliary/util/u_blitter.c +++ b/src/gallium/auxiliary/util/u_blitter.c @@ -100,7 +100,7 @@ struct blitter_context_priv void *velem_state; void *velem_uint_state; void *velem_sint_state; - void *velem_state_readbuf; + void *velem_state_readbuf[4]; /**< X, XY, XYZ, XYZW */ /* Sampler state. */ void *sampler_state; @@ -285,9 +285,19 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) } if (ctx->has_stream_out) { - velem[0].src_format = PIPE_FORMAT_R32_UINT; - velem[0].vertex_buffer_index = ctx->base.vb_slot; - ctx->velem_state_readbuf = pipe->create_vertex_elements_state(pipe, 1, &velem[0]); + static enum pipe_format formats[4] = { + PIPE_FORMAT_R32_UINT, + PIPE_FORMAT_R32G32_UINT, + PIPE_FORMAT_R32G32B32_UINT, + PIPE_FORMAT_R32G32B32A32_UINT + }; + + for (i = 0; i < 4; i++) { + velem[0].src_format = formats[i]; + velem[0].vertex_buffer_index = ctx->base.vb_slot; + ctx->velem_state_readbuf[i] = + pipe->create_vertex_elements_state(pipe, 1, &velem[0]); + } } /* fragment shaders are created on-demand */ @@ -352,8 +362,11 @@ void util_blitter_destroy(struct blitter_context *blitter) pipe->delete_vertex_elements_state(pipe, ctx->velem_sint_state); pipe->delete_vertex_elements_state(pipe, ctx->velem_uint_state); } - if (ctx->velem_state_readbuf) - pipe->delete_vertex_elements_state(pipe, ctx->velem_state_readbuf); + for (i = 0; i < 4; i++) { + if (ctx->velem_state_readbuf[i]) { + pipe->delete_vertex_elements_state(pipe, ctx->velem_state_readbuf[i]); + } + } for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) { if (ctx->fs_texfetch_col[i]) @@ -1739,7 +1752,7 @@ void util_blitter_copy_buffer(struct blitter_context *blitter, vb.stride = 4; pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1, &vb); - pipe->bind_vertex_elements_state(pipe, ctx->velem_state_readbuf); + pipe->bind_vertex_elements_state(pipe, ctx->velem_state_readbuf[0]); pipe->bind_vs_state(pipe, ctx->vs_pos_only); if (ctx->has_geometry_shader) pipe->bind_gs_state(pipe, NULL); @@ -1756,6 +1769,66 @@ void util_blitter_copy_buffer(struct blitter_context *blitter, pipe_so_target_reference(&so_target, NULL); } +void util_blitter_clear_buffer(struct blitter_context *blitter, + struct pipe_resource *dst, + unsigned offset, unsigned size, + unsigned num_channels, + const union pipe_color_union *clear_value) +{ + struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; + struct pipe_context *pipe = ctx->base.pipe; + struct pipe_vertex_buffer vb = {0}; + struct pipe_stream_output_target *so_target; + + assert(num_channels >= 1); + assert(num_channels <= 4); + + /* IMPORTANT: DON'T DO ANY BOUNDS CHECKING HERE! + * + * R600 uses this to initialize texture resources, so width0 might not be + * what you think it is. + */ + + /* Streamout is required. */ + if (!ctx->has_stream_out) { + assert(!"Streamout unsupported in util_blitter_clear_buffer()"); + return; + } + + /* Some alignment is required. */ + if (offset % 4 != 0 || size % 4 != 0) { + assert(!"Bad alignment in util_blitter_clear_buffer()"); + return; + } + + u_upload_data(ctx->upload, 0, num_channels*4, clear_value, + &vb.buffer_offset, &vb.buffer); + vb.stride = 0; + + blitter_set_running_flag(ctx); + blitter_check_saved_vertex_states(ctx); + blitter_disable_render_cond(ctx); + + pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1, &vb); + pipe->bind_vertex_elements_state(pipe, + ctx->velem_state_readbuf[num_channels-1]); + pipe->bind_vs_state(pipe, ctx->vs_pos_only); + if (ctx->has_geometry_shader) + pipe->bind_gs_state(pipe, NULL); + pipe->bind_rasterizer_state(pipe, ctx->rs_discard_state); + + so_target = pipe->create_stream_output_target(pipe, dst, offset, size); + pipe->set_stream_output_targets(pipe, 1, &so_target, 0); + + util_draw_arrays(pipe, PIPE_PRIM_POINTS, 0, size / 4); + + blitter_restore_vertex_states(ctx); + blitter_restore_render_cond(ctx); + blitter_unset_running_flag(ctx); + pipe_so_target_reference(&so_target, NULL); + pipe_resource_reference(&vb.buffer, NULL); +} + /* probably radeon specific */ void util_blitter_custom_resolve_color(struct blitter_context *blitter, struct pipe_resource *dst, -- cgit v1.2.3