Introduction

Objective

IGCL is meant to be a collection of high level APIs for all control aspects of hardware, primarily graphics. This is replacement of legacy Intel CUISDK which used to be released only to OEM’s and selected customers. IGCL allows global control and tweaking of display, media & 3D capabilities.

../_images/control_api_sw_stack.png

Intend of providing API headers, helper files and samples is to help develop specialized GPU control applications & services which need something more than the Operating System provided SDK/API’s. Examples of this include API’s to access DisplayPort AUX bus, using 3DLUT of Intel display pipeline or tweaking media/3D/render performance global feature capabilities. Given the low level nature of these API’s one should be careful in using these.

Display

The display set of API’s help with

  • Graphics adapter enumeration & properties

  • Graphics output enumeration & properties

  • Specific functions to control various display pipeline capabilities like color, scaling, unique configurations, sharpness etc.

See Display API Programming Guide for more details.

Media

The media set of API’s help with

  • Video post processing color feature control, such as color controls and skin tone enhancement.

  • Video post processing quality feature control, such as noise reduction, sharpness and contrast enhancement.

See Media Programming Guide for more details.

Gaming

The gaming/3D set of API’s help with controlling various features like

  • CMAA, texture quality, anisotropic filtering etc.

  • Various special flip modes

Performance & Telemetry

The core performance & telemetry set of API’s help with various Intel(R) oneAPI Level Zero provided functionalities. IGCL API has an instance of Level Zero driver internally which allows it to talk to Level Zero driver directly as and when required. It will provide an API which allows an application vendor to know of the Level Zero device to talk using an IGCL device adapter handle.

Notes: To test the sample along with Level Zero, please ensure that the Level Zero binaries (primarily ze_loader.dll & ze_intel_gpu64.dll) are in a path accessible by the sample. By default, only administrator users have permissions to perform control operations on resources. Most queries are available to any user with the exception of those that could be used for side-channel attacks. The systems administrator can tighten/relax the default permissions for Level Zero. Performance & Telemetry API’s, i.e., Engine/Fan/Telemetry/Frequency/Memory/Overclock/PCI/Power/Temperature are limited to 64-bit applications as of now. This is a Level Zero limitation. Refer https://spec.oneapi.io/versions/latest/index.html for more details on Level Zero

Fundamentals

The following section provides fundamentals of the API design. For more detailed information, refer to the programming guides and detailed specification pages.

Header files can be found at: https://github.com/intel/drivers.gpu.control-library

Terminology

This specification uses key words based on RFC2119 to indicate requirement level. In particular, the following words are used to describe the actions of an implementation of this specification:

  • May - the word may, or the adjective optional, mean that conforming implementations are permitted to, but need not behave as described.

  • Should - the word should, or the adjective recommended, mean that there could be reasons for an implementations to deviate from the behavior described, but that such deviation should be avoided.

  • Must - the word must, or the term required or shall, mean that the behavior described is an absolute requirement of the specification.

Naming Convention

The following naming conventions are followed:

  • All functions are prefixed with ctl

  • All functions use camel case ctlObjectAction convention

  • All macros use all caps CTL_NAME convention

  • All structures, enumerations and other types follow ctl_name_t snake case convention

  • All structure members and function parameters use camel case convention

  • All enumerator values use all caps CTL_ENUM_ETOR_NAME convention

  • All handle types end with handle_t

  • All descriptor structures end with desc_t

  • All property structures end with properties_t

  • All flag enumerations end with flags_t

The following coding conventions are followed:

  • All interface structures are derived from :ref:`ctl-base-interface-t`

  • All function input parameters precede output parameters

  • All functions return ctl_result_t

Versioning

There are multiple versions that should be used by the application to determine compatibility:

API Version - this is the version of the API supported by the device.

  • This is typically used to determine if the device supports the minimum set of APIs required by the application

  • There is a single 32-bit value that represents an entire collection of APIs

  • The value is encoded with 16-bit Major and 16-bit Minor parts

  • Major version increment consist of modified functionality, including deprecate features, and may break backwards-compatibility

  • Minor version increment consist of additional functionality, including promoted extensions, and must retain backwards-compatibility

  • The value is determined from calling ctlInit()

  • In addition to API version, each call will typically have a version field in the interface structure.

Nonpointer structs

  • A struct passed in as a non-pointer variable should not add new variables which can change the struct size.

  • They can change reserved fields aong with the comment of which structure & API version supports it

  • Implementation code should increment the struct specific max supported version.

  • If new fields are added, struct name should precede with an incrementing number and new function interface should be provided which accepts the new structure.

  • If new fields are added, the new function name should precede with an incrementing number. E.g. SetParameterX2([in] handle, [in] struct ctl_param_x2_t)

  • Caller should always fill the struct size and version fields properly as supported by released API spec

Pointer struct

  • A struct passed in as pointer variable can add new variables to it

  • They can change reserved fields but should provide the new struct definition separately.

  • Implementation code should increment the struct specific max supported version.

  • Caller should always fill the struct size and version fields properly as supported by released API spec.

API versioning between multiple driver installations

  • Due to various reasons there can be more than one major version of the IGCL API implementation in the system.

  • The default wrapper implementation provided knows how to select the right major version of the implementation (DLL).

  • Caller should always pass in the version they are coding for and the ctlInit() call will return back with the implementation’s APIs.

  • The value returned will be the API version supported by the device and known by the driver.

  • Caller shall never try to call an interface which the implementation doesn’t have. If caller is using the provided wrapper, this will be taken caller automatically as wrapper won’t find the new interface and will return failure.

  • Figure below describes a flow where three different implementation get into the system and how the behavior will be

  • Initially 1.1 DLL is there in the system from driver of say GPU2 HW.

  • Later user plugs in GPU1 and installs a driver which provides API DLL’s having version 1.2 and 2.0.

  • Now in the system two DLL’s will be kept each being the latest of their respective major versions, i.e. here 2.0 and 1.2.

  • Various types of applications negotiate the interface as shown in the top part of the figure.

  • In the System32 folder only the latest version of the DLL will reside.Even if user downgrades the graphics driver , the newer version in System32 will not be downgraded.

  • The dll packaged with the graphics driver will be copied in to the respective driver store.But the System32 folder will only have the latest version of the dll.

../_images/control_api_version_management.png

Driver Version - this is the version of the driver installed in the system.

  • This is typically used to mitigate driver implementation issues for a feature

  • The value encoding is vendor-specific but must be monotonically increasing

  • The value is determined from calling ctlGetDeviceProperties

Error Handling

The following design philosophies are adopted in order to reduce Host-side overhead:

  • By default, the IGCL API implementation may not perform any form of detailed parameter validation

    • This should be handled by validation layer(s)

  • By default, IGCL API won’t provide any protection against the following:

    • Invalid API programming

    • Invalid function arguments

    • Function infinite loops or recursions

    • Synchronization primitive deadlocks

    • Non-visible memory access by the Host or device

    • Non-resident memory access by the device

  • The IGCL API implementation is not required to perform API validation of any kind

    • The driver should ensure well-behaved applications are not burdened with the overhead needed for non-behaving applications

    • Unless otherwise specified, the driver behavior is undefined when APIs are improperly used

    • For debug purposes, API validation can be enabled via the loader’s validation layer(s)

  • All API functions return ctl_result_t

    • This enumeration contains error codes for the IGCL APIs

    • This allows for a consistent pattern on the application side for catching errors

Multi-threading and Concurrency

The following design philosophies are adopted in order to maximize Host thread concurrency:

  • APIs in general are free-threaded when the device’s object handle is different.

    • the IGCL API should avoid thread-locks for these API calls

  • APIs are not thread-safe when the device’s object handle is the same, except when explicitly noted.

    • the application must ensure multiple threads do not enter an API when the handle is the same

  • APIs are not thread-safe with other APIs that use the same driver’s object handle

    • the application must ensure multiple threads do not enter these APIs when the handle is the same

  • APIs do not support reference counting of handles.

    • the application must track ownership and explicitly free handles and memory

    • the application must ensure that all driver objects and memory are no longer in-use by the device before freeing; otherwise the Host or device may fault

    • no implicit garabage collection is supported by the driver

  • APIs can impact system configuration and it’s application job to ensure it listens to system events provided by OS and provide parameters in sync with current system state

In general, the API is designed to be free-threaded rather than thread-safe. This provides multi-threaded applications with complete control over both threading and locks. This also eliminates unnecessary implementation overhead for single threaded applications and/or very low latency usages.

An application is in direct control over all Host thread creation and usage. IGCL runtime will never implicitly create threads. If there is a need for an implementation to use a background thread, then that thread should be created and provided by the application.

Given the system wide impact of these API’s caller should take care of the possibility of another application changing the state using these or OS API’s. Caller shall register with OS events to know of system configuration changes which might impact the API’s they are interested in and update it’s internal state accordingly.

Application Binary Interface

The IGCL APIs in C are provided to applications by a shared wrapper helper file cApiWrapper.cpp. C/C++ applications must include “igcl_api.h” and preferably use the wrapper while calling the API’s. The wrapper will internally load the required implementation and call respective DLL exported functions. Wrapper approach helps with better control on IGCL API DLL’s update and version management.

IGCL uses the default Application Binary Interface (ABI) of the standard C compiler for the platform. An ABI in this context means the size, alignment, and layout of C data types; the procedure calling convention; and the naming convention for shared library symbols corresponding to C functions. The ABI is backward-compatible for API minor version increments such as adding new functions, appending new enumerators, and using reserved bits in bitfields. ABI is not guaranteed to be backward-compatible for API major version increments such as modifying existing function signatures and structures, removing functions and structures, etc.