[Beignet] [PATCH 1/5] Add some functions to support event in intel gpgpu.

Zhigang Gong zhigang.gong at gmail.com
Wed Aug 7 02:01:23 PDT 2013


On Tue, Aug 06, 2013 at 01:37:25PM +0800, Yang Rong wrote:
> Now runtime prepare command batch first, if can't flush this command
> immediately, call cl_gpgpu_event_pending to append the command to event,
> when the command batch's wait events completed, than call cl_gpgpu_event_resume
> to flush.
> 
> Signed-off-by: Yang Rong <rong.r.yang at intel.com>
> ---
>  src/cl_driver.h         |   24 +++++++++++
>  src/cl_driver_defs.c    |    5 +++
>  src/intel/intel_gpgpu.c |  104 +++++++++++++++++++++++++++++++++++++++++++----
>  3 files changed, 124 insertions(+), 9 deletions(-)
> 
> diff --git a/src/cl_driver.h b/src/cl_driver.h
> index 212beb3..c129246 100644
> --- a/src/cl_driver.h
> +++ b/src/cl_driver.h
> @@ -46,6 +46,9 @@ typedef struct _cl_driver *cl_driver;
>  /* Encapsulates the gpgpu stream of commands */
>  typedef struct _cl_gpgpu *cl_gpgpu;
>  
> +/* Encapsulates the event  of a command stream */
> +typedef struct _cl_gpgpu_event *cl_gpgpu_event;
> +
>  typedef struct _cl_context_prop *cl_context_prop;
>  typedef struct _cl_sampler *cl_sampler;
>  
> @@ -175,6 +178,27 @@ extern cl_gpgpu_batch_end_cb *cl_gpgpu_batch_end;
>  typedef void (cl_gpgpu_flush_cb)(cl_gpgpu);
>  extern cl_gpgpu_flush_cb *cl_gpgpu_flush;
>  
> +/* new a event for a batch buffer */
> +typedef cl_gpgpu_event (cl_gpgpu_event_new_cb)(cl_gpgpu);
> +extern cl_gpgpu_event_new_cb *cl_gpgpu_event_new;
> +
> +/* new a event for a batch buffer */
> +typedef int (cl_gpgpu_event_update_status_cb)(cl_gpgpu_event, int);
> +extern cl_gpgpu_event_update_status_cb *cl_gpgpu_event_update_status;
> +
> +/* new a event for a batch buffer */
> +typedef void (cl_gpgpu_event_pending_cb)(cl_gpgpu, cl_gpgpu_event);
> +extern cl_gpgpu_event_pending_cb *cl_gpgpu_event_pending;
> +
> +/* new a event for a batch buffer */
> +typedef void (cl_gpgpu_event_resume_cb)(cl_gpgpu_event);
> +extern cl_gpgpu_event_resume_cb *cl_gpgpu_event_resume;
> +
> +/* new a event for a batch buffer */
> +typedef void (cl_gpgpu_event_delete_cb)(cl_gpgpu_event);
> +extern cl_gpgpu_event_delete_cb *cl_gpgpu_event_delete;
> +
> +
>  /* Will spawn all threads */
>  typedef void (cl_gpgpu_walker_cb)(cl_gpgpu,
>                                    uint32_t simd_sz,
> diff --git a/src/cl_driver_defs.c b/src/cl_driver_defs.c
> index 4952288..2bcc49d 100644
> --- a/src/cl_driver_defs.c
> +++ b/src/cl_driver_defs.c
> @@ -62,4 +62,9 @@ LOCAL cl_gpgpu_batch_end_cb *cl_gpgpu_batch_end = NULL;
>  LOCAL cl_gpgpu_flush_cb *cl_gpgpu_flush = NULL;
>  LOCAL cl_gpgpu_walker_cb *cl_gpgpu_walker = NULL;
>  LOCAL cl_gpgpu_bind_sampler_cb *cl_gpgpu_bind_sampler = NULL;
> +LOCAL cl_gpgpu_event_new_cb *cl_gpgpu_event_new = NULL;
> +LOCAL cl_gpgpu_event_update_status_cb *cl_gpgpu_event_update_status = NULL;
> +LOCAL cl_gpgpu_event_pending_cb *cl_gpgpu_event_pending = NULL;
> +LOCAL cl_gpgpu_event_resume_cb *cl_gpgpu_event_resume = NULL;
> +LOCAL cl_gpgpu_event_delete_cb *cl_gpgpu_event_delete = NULL;
>  
> diff --git a/src/intel/intel_gpgpu.c b/src/intel/intel_gpgpu.c
> index 2791fbe..9ae0037 100644
> --- a/src/intel/intel_gpgpu.c
> +++ b/src/intel/intel_gpgpu.c
> @@ -1,4 +1,4 @@
> -/* 
> +/*
>   * Copyright © 2012 Intel Corporation
>   *
>   * This library is free software; you can redistribute it and/or
> @@ -57,6 +57,12 @@ typedef struct surface_heap {
>    char surface[256][sizeof(gen6_surface_state_t)];
>  } surface_heap_t;
>  
> +typedef struct intel_event {
> +  intel_batchbuffer_t *batch;
> +  drm_intel_bo* buffer;
> +  int status;
> +} intel_event_t;
> +
>  #define MAX_IF_DESC    32
>  
>  /* We can bind only a limited number of buffers */
> @@ -104,8 +110,8 @@ typedef struct intel_gpgpu intel_gpgpu_t;
>  static void
>  intel_gpgpu_sync(intel_gpgpu_t *gpgpu)
>  {
> -    if (gpgpu->batch->last_bo)
> -	drm_intel_bo_wait_rendering(gpgpu->batch->last_bo);
> +  if (gpgpu->batch->last_bo)
> +    drm_intel_bo_wait_rendering(gpgpu->batch->last_bo);
>  }
>  
>  static void
> @@ -215,7 +221,7 @@ intel_gpgpu_load_vfe_state(intel_gpgpu_t *gpgpu)
>  }
>  
>  static void
> -intel_gpgpu_load_constant_buffer(intel_gpgpu_t *gpgpu) 
> +intel_gpgpu_load_constant_buffer(intel_gpgpu_t *gpgpu)
>  {
>    BEGIN_BATCH(gpgpu->batch, 4);
>    OUT_BATCH(gpgpu->batch, CMD(2,0,1) | (4 - 2));  /* length-2 */
> @@ -233,7 +239,7 @@ intel_gpgpu_load_constant_buffer(intel_gpgpu_t *gpgpu)
>  }
>  
>  static void
> -intel_gpgpu_load_idrt(intel_gpgpu_t *gpgpu) 
> +intel_gpgpu_load_idrt(intel_gpgpu_t *gpgpu)
>  {
>    BEGIN_BATCH(gpgpu->batch, 4);
>    OUT_BATCH(gpgpu->batch, CMD(2,0,2) | (4 - 2)); /* length-2 */
> @@ -246,7 +252,7 @@ intel_gpgpu_load_idrt(intel_gpgpu_t *gpgpu)
>  static const uint32_t gpgpu_l3_config_reg1[] = {
>    0x00080040, 0x02040040, 0x00800040, 0x01000038,
>    0x02000030, 0x01000038, 0x00000038, 0x00000040,
> -  0x0A140091, 0x09100091, 0x08900091, 0x08900091 
> +  0x0A140091, 0x09100091, 0x08900091, 0x08900091
>  };
>  
>  static const uint32_t gpgpu_l3_config_reg2[] = {
> @@ -394,7 +400,7 @@ intel_gpgpu_state_init(intel_gpgpu_t *gpgpu,
>    /* surface state */
>    if(gpgpu->surface_heap_b.bo)
>      dri_bo_unreference(gpgpu->surface_heap_b.bo);
> -  bo = dri_bo_alloc(bufmgr, 
> +  bo = dri_bo_alloc(bufmgr,
>                      "SURFACE_HEAP",
>                      sizeof(surface_heap_t),
>                      32);
> @@ -406,7 +412,7 @@ intel_gpgpu_state_init(intel_gpgpu_t *gpgpu,
>    /* Interface descriptor remap table */
>    if(gpgpu->idrt_b.bo)
>      dri_bo_unreference(gpgpu->idrt_b.bo);
> -  bo = dri_bo_alloc(bufmgr, 
> +  bo = dri_bo_alloc(bufmgr,
>                      "IDRT",
>                      MAX_IF_DESC * sizeof(struct gen6_interface_descriptor),
>                      32);
> @@ -421,7 +427,7 @@ intel_gpgpu_state_init(intel_gpgpu_t *gpgpu,
>    /* sampler state */
>    if (gpgpu->sampler_state_b.bo)
>      dri_bo_unreference(gpgpu->sampler_state_b.bo);
> -  bo = dri_bo_alloc(gpgpu->drv->bufmgr, 
> +  bo = dri_bo_alloc(gpgpu->drv->bufmgr,
>                      "SAMPLER_STATE",
>                      GEN_MAX_SAMPLERS * sizeof(gen6_sampler_state_t),
>                      32);
> @@ -803,6 +809,81 @@ intel_gpgpu_walker(intel_gpgpu_t *gpgpu,
>    ADVANCE_BATCH(gpgpu->batch);
>  }
>  
> +static intel_event_t*
> +intel_gpgpu_event_new(intel_gpgpu_t *gpgpu)
> +{
> +  intel_event_t *event = NULL;
> +  TRY_ALLOC_NO_ERR (event, CALLOC(intel_event_t));
> +
> +  event->status = 0;
Please don't use hard coded number for status. Using enum should be better.

> +  event->batch = NULL;
> +  event->buffer = gpgpu->batch->buffer;
> +  if(event->buffer != NULL)
> +    drm_intel_bo_reference(event->buffer);
> +
> +exit:
> +  return event;
> +error:
> +  cl_free(event);
> +  event = NULL;
> +  goto exit;
> +}
> +
> +static int
> +intel_gpgpu_event_update_status(intel_event_t *event, int wait)
> +{
> +  if(event->status == 1)
> +    return event->status;
> +
> +  if (event->buffer &&
> +      event->batch == NULL &&        //have flushed
> +      !drm_intel_bo_busy(event->buffer)) {
> +    event->status = 1;
> +    drm_intel_bo_unreference(event->buffer);
> +    event->buffer = NULL;
> +    return event->status;
> +  }
> +
> +  if(wait == 0)
> +    return event->status;
> +
> +  if (event->buffer) {
> +    drm_intel_bo_wait_rendering(event->buffer);
> +    event->status = 1;
> +    drm_intel_bo_unreference(event->buffer);
> +    event->buffer = NULL;
> +  }
> +  return event->status;
> +}
> +
> +static void
> +intel_gpgpu_event_pending(intel_gpgpu_t *gpgpu, intel_event_t *event)
> +{
> +  assert(event->buffer);
> +  event->batch = intel_batchbuffer_new(gpgpu->drv);
> +  assert(event->batch);
> +  *event->batch = *gpgpu->batch;
> +  if(event->batch->buffer)
> +    drm_intel_bo_reference(event->batch->buffer);
> +}
> +
> +static void
> +intel_gpgpu_event_resume(intel_event_t *event)
> +{
> +  assert(event->batch);
> +  intel_batchbuffer_flush(event->batch);
> +  intel_batchbuffer_delete(event->batch);
> +  event->batch = NULL;
> +}
I would like to suggest you to add more status checking code at the event
handling functions. For example, if an event is in pending state,
then it should not be pending again and should not be deleted.

> +
> +static void
> +intel_gpgpu_event_delete(intel_event_t *event)
> +{
> +  if(event->buffer)
> +    drm_intel_bo_unreference(event->buffer);
> +  cl_free(event);
> +}
> +
>  LOCAL void
>  intel_set_gpgpu_callbacks(void)
>  {
> @@ -823,5 +904,10 @@ intel_set_gpgpu_callbacks(void)
>    cl_gpgpu_flush = (cl_gpgpu_flush_cb *) intel_gpgpu_flush;
>    cl_gpgpu_walker = (cl_gpgpu_walker_cb *) intel_gpgpu_walker;
>    cl_gpgpu_bind_sampler = (cl_gpgpu_bind_sampler_cb *) intel_gpgpu_bind_sampler;
> +  cl_gpgpu_event_new = (cl_gpgpu_event_new_cb *)intel_gpgpu_event_new;
> +  cl_gpgpu_event_update_status = (cl_gpgpu_event_update_status_cb *)intel_gpgpu_event_update_status;
> +  cl_gpgpu_event_pending = (cl_gpgpu_event_pending_cb *)intel_gpgpu_event_pending;
> +  cl_gpgpu_event_resume = (cl_gpgpu_event_resume_cb *)intel_gpgpu_event_resume;
> +  cl_gpgpu_event_delete = (cl_gpgpu_event_delete_cb *)intel_gpgpu_event_delete;
>  }
>  
> -- 
> 1.7.10.4
> 
> _______________________________________________
> Beignet mailing list
> Beignet at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/beignet


More information about the Beignet mailing list