GFX Object Lifetime Management

This topic only applies to Intel® 64 and IA-32 architectures targeting Intel® Graphics Technology.

The Intel® Graphics Technology runtime maintains various internal objects representing the corresponding processor graphics or driver objects, such as buffer and image objects, as well as task objects. The following general rules describe the lifetime management of such objects:

  • The runtime creates the object at some point after the corresponding GFX API call requests the object to be created, and before it enqueues an offload task that uses the object.

  • The object is kept alive at least until the runtime can reliably prove that:

    • No handle to the object is open and held by the host code.

    • No offload task uses the object.

Lifetime of a Task Object

The internal task object is alive starting from the _GFX_enqueue call that enqueues the corresponding offload task until successful completion of the _GFX_wait call for this task or any other task enqueued after it.

Reference Managed Objects

Reference-managed objects include, but are not limited to, buffer objects and image objects.

The runtime keeps track of all references to reference-managed objects used in each task, as well as references from the user code. A reference-managed object is kept alive as long as at least one reference to it exists as one of the following:

  • Any existing offload task in which the object is or may be used. The runtime is safe and conservative in determining if an object may be used: The accuracy of this decision depends on the object and its implementation.

  • A certain form of reference to the object from your code. The representation of this reference varies from one object to another.

The runtime creates buffer objects to cover shared areas defined by calls to _GFX_share. Thus, a memory area shared by a call to _GFX_share and not yet unshared by a call to _GFX_unshare, is tracked as a reference to the buffer that covers it.

Lifetime of a Buffer Object

The following describes the lifetime of a buffer object in detail:

  1. GFX_share registers an area to share in the internal global list of shared areas.

  2. _GFX_enqueue ensures that all shared areas are covered by buffer objects, while holding internal locks.

    • The runtime ensures that each task sees each shared area through one shared buffer, so no shared area is split between multiple buffers for each task.

    • Sometimes, if the set of shared areas has changed since the previous coverage, a different coverage of areas by buffers may be needed. For example, some existing buffers may only partially cover new areas. In this case, references to such buffers with “invalid coverage” are removed from all shared areas, and such buffers exist only as long as there any tasks that use them are still in the queue. The shared areas, in turn, are covered by new buffers that meet the above requirement

  3. After _GFX_wait detects that an offload task has finished, it deletes references to all buffers held by this task object, which may result in destruction of a buffer if it is not referenced by the host code through a shared area.

    Note

    The set of completed tasks includes the task _GFX_wait waited for, and all earlier submitted tasks that currently exist.

  4. _GFX_unshare removes the area from the list of shared areas and also removes the reference to the buffer covering the shared area, which may result in destruction of a buffer if it is no longer referenced by any existing task.

    Note

    The implementation conservatively assumes that a task may use any shared memory area, and thus any buffer covering a given shared area, that exists when _GFX_enqueue is called for the task.

The image object is kept alive as long as at least one reference to it exists as one of the following:

  • Any existing offload task where the image object is passed as a parameter

  • Any image resource handle in the host code returned from either the C++ constructors GfxImage2D or GfxSharedImage2D, or the C language API call _GFX_create_image_2d.

Lifetime of an Image Object

The following describes the lifetime of an image object in detail:

  1. Either of the C++ constructors GfxImage2D or GfxSharedImage2D, or the C language API call _GFX_create_image_2d, creates the internal image object and returns a handle to it.

    Note

    GfxImage2D and GfxSharedImage2D objects are essentially wrappers over the image resource handle.

  2. For each offload task that uses the image object, the runtime remembers an extra reference to the image object. The runtime destroys the image object when it detects the following:

    • The host code does not keep any image handles, neither by the C++ objects GfxImage2D or GfxSharedImage2D, nor by GfxResourceHandle.

    • No offload task uses the image.

This may happen during either _GFX_wait or GfxImage2D or GfxSharedImage2D constructors, or the _GFX_destroy_image_2d API call. Other deferred cleanup policies are also possible.

For more complete information about compiler optimizations, see our Optimization Notice.