[Mesa-dev] [PATCH] r600g: add support for virtual address space on cayman v8

Michel Dänzer michel at daenzer.net
Mon Jan 9 04:01:45 PST 2012


On Fre, 2012-01-06 at 10:42 -0500, j.glisse at gmail.com wrote: 
> From: Jerome Glisse <jglisse at redhat.com>
> 
> Virtual address space put the userspace in charge of their GPU
> address space. It's up to userspace to bind bo into the virtual
> address space. Command stream can them be executed using the
> IB_VM chunck.
> 
> This patch add support for this configuration. It doesn't remove
> the 64K ib size limit thought this limit can be extanded up to
> 1M for IB_VM chunk.

[...]

> diff --git a/src/gallium/drivers/r600/evergreen_hw_context.c b/src/gallium/drivers/r600/evergreen_hw_context.c
> index 96e8d18..01764ed 100644
> --- a/src/gallium/drivers/r600/evergreen_hw_context.c
> +++ b/src/gallium/drivers/r600/evergreen_hw_context.c
> @@ -1174,8 +1175,10 @@ void evergreen_context_draw(struct r600_context *ctx, const struct r600_draw *dr
>  	pm4[2] = PKT3(PKT3_NUM_INSTANCES, 0, ctx->predicate_drawing);
>  	pm4[3] = draw->vgt_num_instances;
>  	if (draw->indices) {
> -	        pm4[4] = PKT3(PKT3_DRAW_INDEX, 3, ctx->predicate_drawing);
> -		pm4[5] = draw->indices_bo_offset;
> +		va = r600_resource_va(&ctx->screen->screen, (void*)draw->indices);
> +		va += draw->indices_bo_offset;
> +		pm4[4] = PKT3(PKT3_DRAW_INDEX, 3, ctx->predicate_drawing);
> +		pm4[5] = va;
>  		pm4[6] = 0;

pm[6] = va >> 32;


> @@ -2517,15 +2529,20 @@ void evergreen_pipe_init_buffer_resource(struct r600_pipe_context *rctx,
>  }
>  
> 
> -void evergreen_pipe_mod_buffer_resource(struct r600_pipe_resource_state *rstate,
> +void evergreen_pipe_mod_buffer_resource(struct pipe_context *ctx,
> +					struct r600_pipe_resource_state *rstate,
>  					struct r600_resource *rbuffer,
>  					unsigned offset, unsigned stride,
>  					enum radeon_bo_usage usage)
>  {
> +	uint64_t va;
> +
> +	va = r600_resource_va(ctx->screen, (void *)rbuffer);
>  	rstate->bo[0] = rbuffer;
>  	rstate->bo_usage[0] = usage;
> -	rstate->val[0] = offset;
> +	rstate->val[0] = (offset + va) & 0xFFFFFFFFUL;
>  	rstate->val[1] = rbuffer->buf->size - offset - 1;
>  	rstate->val[2] = S_030008_ENDIAN_SWAP(r600_endian_swap(32)) |
> -	                 S_030008_STRIDE(stride);
> +			 S_030008_STRIDE(stride) |
> +			 ((va >> 32UL) & 0xFF);

(((va + offset) >> 32) & 0xFF);


> diff --git a/src/gallium/drivers/r600/r600_hw_context.c b/src/gallium/drivers/r600/r600_hw_context.c
> index 52e0be7..93cb025 100644
> --- a/src/gallium/drivers/r600/r600_hw_context.c
> +++ b/src/gallium/drivers/r600/r600_hw_context.c
> @@ -1570,14 +1573,20 @@ void r600_context_flush(struct r600_context *ctx, unsigned flags)
>  
>  void r600_context_emit_fence(struct r600_context *ctx, struct r600_resource *fence_bo, unsigned offset, unsigned value)
>  {
> +	uint64_t va;
> +
>  	r600_need_cs_space(ctx, 10, FALSE);
>  
> +	va = r600_resource_va(&ctx->screen->screen, (void*)fence_bo);
> +	va = va + (offset << 2);
> +
>  	ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 0, 0);
>  	ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_PS_PARTIAL_FLUSH) | EVENT_INDEX(4);
>  	ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE_EOP, 4, 0);
>  	ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_CACHE_FLUSH_AND_INV_TS_EVENT) | EVENT_INDEX(5);
> -	ctx->pm4[ctx->pm4_cdwords++] = offset << 2;             /* ADDRESS_LO */
> -	ctx->pm4[ctx->pm4_cdwords++] = (1 << 29) | (0 << 24);   /* DATA_SEL | INT_EN | ADDRESS_HI */
> +	ctx->pm4[ctx->pm4_cdwords++] = va & 0xFFFFFFFFUL;       /* ADDRESS_LO */
> +	/* DATA_SEL | INT_EN | ADDRESS_HI */
> +	ctx->pm4[ctx->pm4_cdwords++] = (1 << 29) | (0 << 24) | ((va >> 32UL) & 0xFFFFFFFFUL);

ctx->pm4[ctx->pm4_cdwords++] = (1 << 29) | (0 << 24) | ((va >> 32) & 0xFF);


> @@ -1684,19 +1694,22 @@ void r600_query_begin(struct r600_context *ctx, struct r600_query *query)
>  	}
>  
>  	/* emit begin query */
> +	va = r600_resource_va(&ctx->screen->screen, (void*)query->buffer);
> +	va += query->results_end;
> +
>  	switch (query->type) {
>  	case PIPE_QUERY_OCCLUSION_COUNTER:
>  	case PIPE_QUERY_OCCLUSION_PREDICATE:
>  		ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE, 2, 0);
>  		ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_ZPASS_DONE) | EVENT_INDEX(1);
> -		ctx->pm4[ctx->pm4_cdwords++] = query->results_end;
> -		ctx->pm4[ctx->pm4_cdwords++] = 0;
> +		ctx->pm4[ctx->pm4_cdwords++] = va & 0xFFFFFFFFUL;
> +		ctx->pm4[ctx->pm4_cdwords++] = (va >> 32UL) & 0xFFFFFFFFUL;
>  		break;
>  	case PIPE_QUERY_TIME_ELAPSED:
>  		ctx->pm4[ctx->pm4_cdwords++] = PKT3(PKT3_EVENT_WRITE_EOP, 4, 0);
>  		ctx->pm4[ctx->pm4_cdwords++] = EVENT_TYPE(EVENT_TYPE_CACHE_FLUSH_AND_INV_TS_EVENT) | EVENT_INDEX(5);
> -		ctx->pm4[ctx->pm4_cdwords++] = query->results_end;
> -		ctx->pm4[ctx->pm4_cdwords++] = (3 << 29);
> +		ctx->pm4[ctx->pm4_cdwords++] = va & 0xFFFFFFFFUL;
> +		ctx->pm4[ctx->pm4_cdwords++] = (3 << 29) | ((va >> 32UL) & 0xFFFFFFFFUL);
>  		ctx->pm4[ctx->pm4_cdwords++] = 0;
>  		ctx->pm4[ctx->pm4_cdwords++] = 0;
>  		break;

These '& 0xFFFFFFFFUL's are no-ops. Drop the ones for the low bits, the
ones for the high bits should probably be '& 0xFF'?


> diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
> index ccf9c4f..8ef0c18 100644
> --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
> +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
> @@ -151,9 +163,85 @@ static boolean radeon_bo_is_busy(struct pb_buffer *_buf,
[...] 
> +
> +static void radeon_bomgr_force_va(struct radeon_bomgr *mgr, uint64_t va, uint64_t size)
> +{
> +    pipe_mutex_lock(mgr->bo_handles_mutex);
> +    if (va >= mgr->va_offset) {
> +        mgr->va_offset = va + size;

Doesn't this need to add a hole if va > mgr->va_offset?


> +    } else {
> +        struct radeon_bo_va_hole *hole, *n;
> +        uint64_t stmp, etmp;
> +
> +        /* free all hole that fall into the range
> +         * NOTE that we might loose virtual address space

Typos: 'holes', 'lose'


> +static void radeon_bomgr_free_va(struct radeon_bomgr *mgr, uint64_t va, uint64_t size)
> +{
> +    pipe_mutex_lock(mgr->bo_handles_mutex);
> +    if ((va + size) == mgr->va_offset) {
> +        mgr->va_offset = va;
> +    } else {
> +        struct radeon_bo_va_hole *hole;
> +
> +        /* FIXME on allocation failure we just loose virtual address space

'lose'


> +        r = drmCommandWriteRead(ws->fd, DRM_RADEON_GEM_VA, &va, sizeof(va));
> +        if (r && va.operation == RADEON_VA_RESULT_ERROR) {
> +            fprintf(stderr, "radeon: Failed to open a buffer:\n");

This error message doesn't seem very specific / useful.


> diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c
> index 442bd2a..8124016 100644
> --- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c
> +++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c
> @@ -138,9 +138,11 @@ static boolean radeon_get_drm_value(int fd, unsigned request,
>      info.request = request;
>  
>      retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info));
> -    if (retval && errname) {
> -        fprintf(stderr, "radeon: Failed to get %s, error number %d\n",
> -                errname, retval);
> +    if (retval) {
> +        if (errname) {
> +            fprintf(stderr, "radeon: Failed to get %s, error number %d\n",
> +                    errname, retval);
> +        }
>          return FALSE;
>      }
>      return TRUE;

This fix should probably be a change of its own.


-- 
Earthling Michel Dänzer           |                   http://www.amd.com
Libre software enthusiast         |          Debian, X and DRI developer


More information about the mesa-dev mailing list