[Mesa-dev] [PATCH 15/18] radeonsi: upload constants into VRAM instead of GTT

Nicolai Hähnle nhaehnle at gmail.com
Thu Feb 16 15:21:43 UTC 2017


On 16.02.2017 13:53, Marek Olšák wrote:
> From: Marek Olšák <marek.olsak at amd.com>
>
> This lowers lgkm wait cycles by 30% on VI and normal conditions.
> The might be a measurable improvement when CE is disabled (radeon)
> or under L2 thrashing.

Good idea. I'm just wondering if all the users of const upload end up as 
streaming writes? I hope we don't accidentally hit some place where 
writes from the CPU end up extremely slow, e.g. where st/mesa uploads 
some structures.

Nicolai


> ---
>  src/gallium/drivers/radeon/r600_pipe_common.c | 11 ++++++++---
>  src/gallium/drivers/radeonsi/si_compute.c     |  4 ++--
>  src/gallium/drivers/radeonsi/si_descriptors.c |  6 +++---
>  src/gallium/drivers/radeonsi/si_state.c       |  7 +++++--
>  4 files changed, 18 insertions(+), 10 deletions(-)
>
> diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c b/src/gallium/drivers/radeon/r600_pipe_common.c
> index d573b39..1781584 100644
> --- a/src/gallium/drivers/radeon/r600_pipe_common.c
> +++ b/src/gallium/drivers/radeon/r600_pipe_common.c
> @@ -600,21 +600,25 @@ bool r600_common_context_init(struct r600_common_context *rctx,
>  	rctx->allocator_zeroed_memory =
>  		u_suballocator_create(&rctx->b, rscreen->info.gart_page_size,
>  				      0, PIPE_USAGE_DEFAULT, 0, true);
>  	if (!rctx->allocator_zeroed_memory)
>  		return false;
>
>  	rctx->b.stream_uploader = u_upload_create(&rctx->b, 1024 * 1024,
>  						  0, PIPE_USAGE_STREAM);
>  	if (!rctx->b.stream_uploader)
>  		return false;
> -	rctx->b.const_uploader = rctx->b.stream_uploader;
> +
> +	rctx->b.const_uploader = u_upload_create(&rctx->b, 128 * 1024,
> +						 0, PIPE_USAGE_DEFAULT);
> +	if (!rctx->b.const_uploader)
> +		return false;
>
>  	rctx->ctx = rctx->ws->ctx_create(rctx->ws);
>  	if (!rctx->ctx)
>  		return false;
>
>  	if (rscreen->info.has_sdma && !(rscreen->debug_flags & DBG_NO_ASYNC_DMA)) {
>  		rctx->dma.cs = rctx->ws->cs_create(rctx->ctx, RING_DMA,
>  						   r600_flush_dma_ring,
>  						   rctx);
>  		rctx->dma.flush = r600_flush_dma_ring;
> @@ -642,23 +646,24 @@ void r600_common_context_cleanup(struct r600_common_context *rctx)
>  	if (rctx->query_result_shader)
>  		rctx->b.delete_compute_state(&rctx->b, rctx->query_result_shader);
>
>  	if (rctx->gfx.cs)
>  		rctx->ws->cs_destroy(rctx->gfx.cs);
>  	if (rctx->dma.cs)
>  		rctx->ws->cs_destroy(rctx->dma.cs);
>  	if (rctx->ctx)
>  		rctx->ws->ctx_destroy(rctx->ctx);
>
> -	if (rctx->b.stream_uploader) {
> +	if (rctx->b.stream_uploader)
>  		u_upload_destroy(rctx->b.stream_uploader);
> -	}
> +	if (rctx->b.const_uploader)
> +		u_upload_destroy(rctx->b.const_uploader);
>
>  	slab_destroy_child(&rctx->pool_transfers);
>
>  	if (rctx->allocator_zeroed_memory) {
>  		u_suballocator_destroy(rctx->allocator_zeroed_memory);
>  	}
>  	rctx->ws->fence_reference(&rctx->last_gfx_fence, NULL);
>  	rctx->ws->fence_reference(&rctx->last_sdma_fence, NULL);
>  }
>
> diff --git a/src/gallium/drivers/radeonsi/si_compute.c b/src/gallium/drivers/radeonsi/si_compute.c
> index 381837c..88d72c1 100644
> --- a/src/gallium/drivers/radeonsi/si_compute.c
> +++ b/src/gallium/drivers/radeonsi/si_compute.c
> @@ -496,21 +496,21 @@ static void si_setup_user_sgprs_co_v2(struct si_context *sctx,
>
>  		dispatch.grid_size_x = info->grid[0] * info->block[0];
>  		dispatch.grid_size_y = info->grid[1] * info->block[1];
>  		dispatch.grid_size_z = info->grid[2] * info->block[2];
>
>  		dispatch.private_segment_size = program->private_size;
>  		dispatch.group_segment_size = program->local_size;
>
>  		dispatch.kernarg_address = kernel_args_va;
>
> -		u_upload_data(sctx->b.b.stream_uploader, 0, sizeof(dispatch),
> +		u_upload_data(sctx->b.b.const_uploader, 0, sizeof(dispatch),
>                                256, &dispatch, &dispatch_offset,
>                                (struct pipe_resource**)&dispatch_buf);
>
>  		if (!dispatch_buf) {
>  			fprintf(stderr, "Error: Failed to allocate dispatch "
>  					"packet.");
>  		}
>  		radeon_add_to_buffer_list(&sctx->b, &sctx->b.gfx, dispatch_buf,
>  				  RADEON_USAGE_READ, RADEON_PRIO_CONST_BUFFER);
>
> @@ -558,21 +558,21 @@ static void si_upload_compute_input(struct si_context *sctx,
>  	unsigned num_work_size_bytes = program->use_code_object_v2 ? 0 : 36;
>  	uint32_t kernel_args_offset = 0;
>  	uint32_t *kernel_args;
>  	void *kernel_args_ptr;
>  	uint64_t kernel_args_va;
>  	unsigned i;
>
>  	/* The extra num_work_size_bytes are for work group / work item size information */
>  	kernel_args_size = program->input_size + num_work_size_bytes;
>
> -	u_upload_alloc(sctx->b.b.stream_uploader, 0, kernel_args_size,
> +	u_upload_alloc(sctx->b.b.const_uploader, 0, kernel_args_size,
>  		       sctx->screen->b.info.tcc_cache_line_size,
>  		       &kernel_args_offset,
>  		       (struct pipe_resource**)&input_buffer, &kernel_args_ptr);
>
>  	kernel_args = (uint32_t*)kernel_args_ptr;
>  	kernel_args_va = input_buffer->gpu_address + kernel_args_offset;
>
>  	if (!code_object) {
>  		for (i = 0; i < 3; i++) {
>  			kernel_args[i] = info->grid[i];
> diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
> index b4f1fbf..a41b243 100644
> --- a/src/gallium/drivers/radeonsi/si_descriptors.c
> +++ b/src/gallium/drivers/radeonsi/si_descriptors.c
> @@ -228,21 +228,21 @@ static bool si_upload_descriptors(struct si_context *sctx,
>  			radeon_emit(sctx->ce_ib, desc->ce_offset + begin * 4);
>  			radeon_emit_array(sctx->ce_ib, list + begin, count);
>  		}
>
>  		if (!si_ce_upload(sctx, desc->ce_offset, list_size,
>  		                           &desc->buffer_offset, &desc->buffer))
>  			return false;
>  	} else {
>  		void *ptr;
>
> -		u_upload_alloc(sctx->b.b.stream_uploader, 0, list_size,
> +		u_upload_alloc(sctx->b.b.const_uploader, 0, list_size,
>  			       sctx->screen->b.info.tcc_cache_line_size,
>  			       &desc->buffer_offset,
>  			       (struct pipe_resource**)&desc->buffer, &ptr);
>  		if (!desc->buffer)
>  			return false; /* skip the draw call */
>
>  		util_memcpy_cpu_to_le32(ptr, desc->list, list_size);
>  		desc->gpu_list = ptr;
>
>  		radeon_add_to_buffer_list(&sctx->b, &sctx->b.gfx, desc->buffer,
> @@ -956,21 +956,21 @@ bool si_upload_vertex_buffer_descriptors(struct si_context *sctx)
>
>  	if (!sctx->vertex_buffers_dirty || !count || !velems)
>  		return true;
>
>  	unsigned first_vb_use_mask = velems->first_vb_use_mask;
>
>  	/* Vertex buffer descriptors are the only ones which are uploaded
>  	 * directly through a staging buffer and don't go through
>  	 * the fine-grained upload path.
>  	 */
> -	u_upload_alloc(sctx->b.b.stream_uploader, 0,
> +	u_upload_alloc(sctx->b.b.const_uploader, 0,
>  		       desc_list_byte_size,
>  		       si_optimal_tcc_alignment(sctx, desc_list_byte_size),
>  		       &desc->buffer_offset,
>  		       (struct pipe_resource**)&desc->buffer, (void**)&ptr);
>  	if (!desc->buffer)
>  		return false;
>
>  	radeon_add_to_buffer_list(&sctx->b, &sctx->b.gfx,
>  			      desc->buffer, RADEON_USAGE_READ,
>  			      RADEON_PRIO_DESCRIPTORS);
> @@ -1044,21 +1044,21 @@ static struct si_descriptors *
>  si_const_buffer_descriptors(struct si_context *sctx, unsigned shader)
>  {
>  	return &sctx->descriptors[si_const_buffer_descriptors_idx(shader)];
>  }
>
>  void si_upload_const_buffer(struct si_context *sctx, struct r600_resource **rbuffer,
>  			    const uint8_t *ptr, unsigned size, uint32_t *const_offset)
>  {
>  	void *tmp;
>
> -	u_upload_alloc(sctx->b.b.stream_uploader, 0, size,
> +	u_upload_alloc(sctx->b.b.const_uploader, 0, size,
>  		       si_optimal_tcc_alignment(sctx, size),
>  		       const_offset,
>  		       (struct pipe_resource**)rbuffer, &tmp);
>  	if (*rbuffer)
>  		util_memcpy_cpu_to_le32(tmp, ptr, size);
>  }
>
>  static void si_set_constant_buffer(struct si_context *sctx,
>  				   struct si_buffer_resources *buffers,
>  				   unsigned descriptors_idx,
> diff --git a/src/gallium/drivers/radeonsi/si_state.c b/src/gallium/drivers/radeonsi/si_state.c
> index f53f8dd..81592a7 100644
> --- a/src/gallium/drivers/radeonsi/si_state.c
> +++ b/src/gallium/drivers/radeonsi/si_state.c
> @@ -3519,22 +3519,25 @@ static void si_set_vertex_buffers(struct pipe_context *ctx,
>  	if (buffers) {
>  		for (i = 0; i < count; i++) {
>  			const struct pipe_vertex_buffer *src = buffers + i;
>  			struct pipe_vertex_buffer *dsti = dst + i;
>
>  			if (unlikely(src->user_buffer)) {
>  				/* Zero-stride attribs only. */
>  				assert(src->stride == 0);
>
>  				/* Assume the attrib has 4 dwords like the vbo
> -				 * module. This is also a good upper bound. */
> -				u_upload_data(sctx->b.b.stream_uploader, 0, 16, 16,
> +				 * module. This is also a good upper bound.
> +				 *
> +				 * Use const_uploader to upload into VRAM directly.
> +				 */
> +				u_upload_data(sctx->b.b.const_uploader, 0, 16, 16,
>  					      src->user_buffer,
>  					      &dsti->buffer_offset,
>  					      &dsti->buffer);
>  				dsti->stride = 0;
>  			} else {
>  				struct pipe_resource *buf = src->buffer;
>
>  				pipe_resource_reference(&dsti->buffer, buf);
>  				dsti->buffer_offset = src->buffer_offset;
>  				dsti->stride = src->stride;
>



More information about the mesa-dev mailing list