Skip to content

Commit

Permalink
Explicitly define which info queries are optional.
Browse files Browse the repository at this point in the history
This is now reflected in the spec and in the CTS tests.

Also includes a number of minor fixes for adapter implementations of
related info queries.
  • Loading branch information
aarongreig committed Nov 26, 2024
1 parent 38ee6ce commit 7470d9e
Show file tree
Hide file tree
Showing 57 changed files with 509 additions and 223 deletions.
82 changes: 43 additions & 39 deletions include/ur_api.h

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions scripts/YaML.md
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ plural form *enumerators* is abbreviated to `etors`.
- An etor requires the following scalar fields: {`name`, `desc`}
+ `desc` will be used as the etors's description comment
+ If the enum has `typed_etors`, `desc` must begin with type identifier: {`"[type]"`}
+ `desc` may contain the [optional-query] annotation. This denotes the etor as an info query which is optional for adapters to implement, and may legally result in a non-success error code.
+ `name` must be a unique ISO-C standard identifier, and be all caps
- An etor may take the following optional scalar field: {`value`, `version`}
+ `value` must be an ISO-C standard identifier
Expand Down
18 changes: 18 additions & 0 deletions scripts/core/PROG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,24 @@ explicitly created against a context.
// Release the context handle
${x}ContextRelease(hContext);
Object Queries
==============

Queries to get information from API objects follow a common pattern. The entry
points for this are generally of the form:

.. code-block::
ObjectGetInfo(ur_object_handle_t hObject, ur_object_info_t propName,
size_t propSize, void *pPropValue, size_t *pPropSizeRet)
where ``propName`` selects the information to query out. The object info enum
representing possible queries will generally be found in the enums section of
the relevant object. Some info queries would be difficult or impossible to
support for certain backends, these are denoted with [optional-query] in the
enum description. Using any enum marked optional in this way may result in
${X}_RESULT_ERROR_UNSUPPORTED_ENUMERATION if the adapter doesn't support it.

Programs and Kernels
====================

Expand Down
8 changes: 4 additions & 4 deletions scripts/core/context.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,16 +102,16 @@ etors:
- name: USM_FILL2D_SUPPORT
desc: "[$x_bool_t] to indicate if the $xEnqueueUSMFill2D entrypoint is supported."
- name: ATOMIC_MEMORY_ORDER_CAPABILITIES
desc: "[$x_memory_order_capability_flags_t] return a bit-field of atomic memory order capabilities."
desc: "[$x_memory_order_capability_flags_t][optional-query] return a bit-field of atomic memory order capabilities."
- name: ATOMIC_MEMORY_SCOPE_CAPABILITIES
desc: "[$x_memory_scope_capability_flags_t] return a bit-field of atomic memory scope capabilities."
desc: "[$x_memory_scope_capability_flags_t][optional-query] return a bit-field of atomic memory scope capabilities."
- name: ATOMIC_FENCE_ORDER_CAPABILITIES
desc: |
[$x_memory_order_capability_flags_t] return a bit-field of atomic memory fence order capabilities.
[$x_memory_order_capability_flags_t][optional-query] return a bit-field of atomic memory fence order capabilities.
Zero is returned if the backend does not support context-level fences.
- name: ATOMIC_FENCE_SCOPE_CAPABILITIES
desc: |
[$x_memory_scope_capability_flags_t] return a bit-field of atomic memory fence scope capabilities.
[$x_memory_scope_capability_flags_t][optional-query] return a bit-field of atomic memory fence scope capabilities.
Zero is returned if the backend does not support context-level fences.
--- #--------------------------------------------------------------------------
type: function
Expand Down
30 changes: 15 additions & 15 deletions scripts/core/device.yml
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ etors:
- name: VENDOR_ID
desc: "[uint32_t] vendor Id of the device"
- name: DEVICE_ID
desc: "[uint32_t] Id of the device"
desc: "[uint32_t][optional-query] Id of the device"
- name: MAX_COMPUTE_UNITS
desc: "[uint32_t] the number of compute units"
- name: MAX_WORK_ITEM_DIMENSIONS
Expand Down Expand Up @@ -248,7 +248,7 @@ etors:
- name: MAX_CLOCK_FREQUENCY
desc: "[uint32_t] max clock frequency in MHz"
- name: MEMORY_CLOCK_RATE
desc: "[uint32_t] memory clock frequency in MHz"
desc: "[uint32_t][optional-query] memory clock frequency in MHz"
- name: ADDRESS_BITS
desc: "[uint32_t] address bits"
- name: MAX_MEM_ALLOC_SIZE
Expand Down Expand Up @@ -290,7 +290,7 @@ etors:
- name: GLOBAL_MEM_SIZE
desc: "[uint64_t] size of global memory in bytes"
- name: GLOBAL_MEM_FREE
desc: "[uint64_t] size of global memory which is free in bytes"
desc: "[uint64_t][optional-query] size of global memory which is free in bytes"
- name: MAX_CONSTANT_BUFFER_SIZE
desc: "[uint64_t] max constant buffer size in bytes"
- name: MAX_CONSTANT_ARGS
Expand Down Expand Up @@ -377,23 +377,23 @@ etors:
- name: USM_SYSTEM_SHARED_SUPPORT
desc: "[$x_device_usm_access_capability_flags_t] support USM system wide shared memory access"
- name: UUID
desc: "[uint8_t[]] return device UUID"
desc: "[uint8_t[]][optional-query] return device UUID"
- name: PCI_ADDRESS
desc: "[char[]] return device PCI address"
desc: "[char[]][optional-query] return device PCI address"
- name: GPU_EU_COUNT
desc: "[uint32_t] return Intel GPU EU count"
desc: "[uint32_t][optional-query] return Intel GPU EU count"
- name: GPU_EU_SIMD_WIDTH
desc: "[uint32_t] return Intel GPU EU SIMD width"
desc: "[uint32_t][optional-query] return Intel GPU EU SIMD width"
- name: GPU_EU_SLICES
desc: "[uint32_t] return Intel GPU number of slices"
desc: "[uint32_t][optional-query] return Intel GPU number of slices"
- name: GPU_EU_COUNT_PER_SUBSLICE
desc: "[uint32_t] return Intel GPU EU count per subslice"
desc: "[uint32_t][optional-query] return Intel GPU EU count per subslice"
- name: GPU_SUBSLICES_PER_SLICE
desc: "[uint32_t] return Intel GPU number of subslices per slice"
desc: "[uint32_t][optional-query] return Intel GPU number of subslices per slice"
- name: GPU_HW_THREADS_PER_EU
desc: "[uint32_t] return Intel GPU number of threads per EU"
desc: "[uint32_t][optional-query] return Intel GPU number of threads per EU"
- name: MAX_MEMORY_BANDWIDTH
desc: "[uint32_t] return max memory bandwidth in Mb/s"
desc: "[uint32_t][optional-query] return max memory bandwidth in Mb/s"
- name: IMAGE_SRGB
desc: "[$x_bool_t] device supports sRGB images"
- name: BUILD_ON_SUBDEVICE
Expand All @@ -418,7 +418,7 @@ etors:
- name: KERNEL_SET_SPECIALIZATION_CONSTANTS
desc: "[$x_bool_t] support the $xKernelSetSpecializationConstants entry point"
- name: MEMORY_BUS_WIDTH
desc: "[uint32_t] return the width in bits of the memory bus interface of the device."
desc: "[uint32_t][optional-query] return the width in bits of the memory bus interface of the device."
- name: MAX_WORK_GROUPS_3D
desc: "[size_t[3]] return max 3D work groups"
- name: ASYNC_BARRIER
Expand All @@ -428,9 +428,9 @@ etors:
- name: HOST_PIPE_READ_WRITE_SUPPORTED
desc: "[$x_bool_t] Return true if the device supports enqueueing commands to read and write pipes from the host."
- name: MAX_REGISTERS_PER_WORK_GROUP
desc: "[uint32_t] The maximum number of registers available per block."
desc: "[uint32_t][optional-query] The maximum number of registers available per block."
- name: IP_VERSION
desc: "[uint32_t] The device IP version. The meaning of the device IP version is implementation-defined, but newer devices should have a higher version than older devices."
desc: "[uint32_t][optional-query] The device IP version. The meaning of the device IP version is implementation-defined, but newer devices should have a higher version than older devices."
- name: VIRTUAL_MEMORY_SUPPORT
desc: "[$x_bool_t] return true if the device supports virtual memory."
- name: ESIMD_SUPPORT
Expand Down
12 changes: 6 additions & 6 deletions scripts/core/kernel.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ etors:
- name: ATTRIBUTES
desc: "[char[]] Return null-terminated kernel attributes string."
- name: NUM_REGS
desc: "[uint32_t] Return the number of registers used by the compiled kernel (device specific)."
desc: "[uint32_t][optional-query] Return the number of registers used by the compiled kernel."
--- #--------------------------------------------------------------------------
type: enum
desc: "Get Kernel Work Group information"
Expand All @@ -133,7 +133,7 @@ name: $x_kernel_group_info_t
typed_etors: True
etors:
- name: GLOBAL_WORK_SIZE
desc: "[size_t[3]] Return Work Group maximum global size"
desc: "[size_t[3]][optional-query] Return Work Group maximum global size"
- name: WORK_GROUP_SIZE
desc: "[size_t] Return maximum Work Group size"
- name: COMPILE_WORK_GROUP_SIZE
Expand All @@ -146,12 +146,12 @@ etors:
desc: "[size_t] Return minimum amount of private memory in bytes used by each work item in the Kernel"
- name: COMPILE_MAX_WORK_GROUP_SIZE
desc: |
[size_t[3]] Return the maximum Work Group size guaranteed by the
source code, or (0, 0, 0) if unspecified
[size_t[3]][optional-query] Return the maximum Work Group size guaranteed
by the source code, or (0, 0, 0) if unspecified
- name: COMPILE_MAX_LINEAR_WORK_GROUP_SIZE
desc: |
[size_t] Return the maximum linearized Work Group size (X * Y * Z)
guaranteed by the source code, or 0 if unspecified
[size_t][optional-query] Return the maximum linearized Work Group size
(X * Y * Z) guaranteed by the source code, or 0 if unspecified
--- #--------------------------------------------------------------------------
type: enum
desc: "Get Kernel SubGroup information"
Expand Down
4 changes: 2 additions & 2 deletions scripts/core/program.yml
Original file line number Diff line number Diff line change
Expand Up @@ -387,9 +387,9 @@ etors:
- name: BINARIES
desc: "[unsigned char[]] Return program binaries for all devices for this Program."
- name: NUM_KERNELS
desc: "[size_t] Number of kernels in Program, return type size_t."
desc: "[size_t][optional-query] Number of kernels in Program, return type size_t."
- name: KERNEL_NAMES
desc: "[char[]] Return a null-terminated, semi-colon separated list of kernel names in Program."
desc: "[char[]][optional-query] Return a null-terminated, semi-colon separated list of kernel names in Program."
--- #--------------------------------------------------------------------------
type: function
desc: "Query information about a Program object"
Expand Down
2 changes: 1 addition & 1 deletion scripts/core/queue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ etors:
if the queue was created with the `ON_DEVICE` queue flag, otherwise
`$xQueueGetInfo` will return `$X_RESULT_ERROR_INVALID_QUEUE`.
- name: EMPTY
desc: "[$x_bool_t] return true if the queue was empty at the time of the query"
desc: "[$x_bool_t][optional-query] return true if the queue was empty at the time of the query."
--- #--------------------------------------------------------------------------
type: enum
desc: "Queue property flags"
Expand Down
2 changes: 1 addition & 1 deletion scripts/core/usm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ etors:
- name: DEVICE
desc: "[$x_device_handle_t] Memory allocation device info"
- name: POOL
desc: "[$x_usm_pool_handle_t] Memory allocation pool info"
desc: "[$x_usm_pool_handle_t][optional-query] Memory allocation pool info"
--- #--------------------------------------------------------------------------
type: enum
desc: "USM memory advice"
Expand Down
21 changes: 21 additions & 0 deletions scripts/generate_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,3 +548,24 @@ def generate_level_zero_queue_api(path, section, namespace, tags, version, specs
specs=specs,
meta=meta)
print("QUEUE Generated %s lines of code.\n" % loc)

"""
Entry-point:
generates headers used by the CTS, for example containing meta-information
about info query enums
"""
def generate_cts_headers(path, section, namespace, tags, version, specs, meta):
template = "optional_queries.h.mako"
fin = os.path.join("templates", template)
name = "optional_queries"
filename = "optional_queries.h"
dstpath = os.path.join(path, "conformance", "testing", "include", "uur")
fout = os.path.join(dstpath, filename)

print("Generating %s..." % fout)

loc = util.makoWrite(fin, fout,
filename = name, namespace = namespace,
tags = tags, specs = specs, meta = meta)

print("CTS Generated %s lines of code.\n" % loc)
4 changes: 4 additions & 0 deletions scripts/json2src.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def add_argument(parser, name, help, default=False):
add_argument(parser, "common", "generation of common files.", True)
add_argument(parser, "tools", "generation of common files.", True)
add_argument(parser, "l0_queue", "generation of l0 queue abstractions.", True)
add_argument(parser, "cts", "generation of cts headers", True)
parser.add_argument("--debug", action='store_true', help="dump intermediate data to disk.")
parser.add_argument("--sections", type=list, default=None, help="Optional list of sections for which to generate source, default is all")
parser.add_argument("--ver", type=str, default="1.0", help="specification version to generate.")
Expand All @@ -45,6 +46,7 @@ def add_argument(parser, name, help, default=False):

srcpath = os.path.join(args.out_dir, "source")
toolspath = os.path.join(args.out_dir, "tools")
testpath = os.path.join(args.out_dir, "test")

for idx, specs in enumerate(input['specs']):
config = input['configs'][idx]
Expand All @@ -63,6 +65,8 @@ def add_argument(parser, name, help, default=False):
generate_code.generate_tools(toolspath, config['name'], config['namespace'], config['tags'], args.ver, specs, input['meta'])
if args.l0_queue:
generate_code.generate_level_zero_queue_api(srcpath, config['name'], config['namespace'], config['tags'], args.ver, specs, input['meta'])
if args.cts:
generate_code.generate_cts_headers(testpath, config['name'], config['namespace'], config['tags'], args.ver, specs, input['meta'])

if args.debug:
util.makoFileListWrite("generated.json")
Expand Down
35 changes: 34 additions & 1 deletion scripts/templates/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,18 @@ def is_global(item, tags):
except:
return False

"""
Extracts traits from an enumerator
"""
class etor_traits:
RE_OPTIONAL_QUERY = r".*\[optional-query\].*"

@classmethod
def is_optional_query(cls, item):
try:
return True if re.match(cls.RE_OPTIONAL_QUERY, item['desc']) else False
except:
return False

"""
Public:
Expand Down Expand Up @@ -780,7 +792,7 @@ def make_etor_name(namespace, tags, enum, etor, meta=None):
returns the associated type of an etor from a typed enum
"""
def etor_get_associated_type(namespace, tags, item):
match = re.match(r'^\[(.+)\]\s', item['desc'])
match = re.match(r'^\[([$A-Za-z0-9_*[\] ]+)\]', item['desc'])
if match:
associated_type = match.group(1)
return subt(namespace, tags, associated_type)
Expand Down Expand Up @@ -1692,3 +1704,24 @@ def transform_queue_related_function_name(namespace, tags, obj, format = ["name"
params = params[1:]

return "{}({})".format(function_name, ", ".join(params))

"""
Public:
Returns a dictionary mapping info enum types to the list of optional queries
within that enum. If an enum type doesn't have any optional queries it will
not appear in the dictionary as a key.
"""
def get_optional_queries(specs, namespace, tags):
optional_queries = {}
for s in specs:
for obj in s['objects']:
if obj['type'] == 'enum':
optional_etors = []
for e in obj['etors']:
if etor_traits.is_optional_query(e):
name = make_enum_name(namespace, tags, e)
optional_etors.append(name)
if optional_etors:
type_name = make_type_name(namespace, tags, obj)
optional_queries[type_name] = optional_etors
return optional_queries
45 changes: 45 additions & 0 deletions scripts/templates/optional_queries.h.mako
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<%!
import re
from templates import helper as th
%><%
optional_queries = th.get_optional_queries(specs, namespace, tags)
%>/*
*
* Copyright (C) 2024 Intel Corporation
*
* Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions.
* See LICENSE.TXT
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*
* @file ${filename}.h
*
*/

// Auto-generated file, do not edit.

#pragma once

#include <algorithm>
#include <array>
#include <ur_api.h>

namespace uur {

template <class T> bool isQueryOptional(T) { return false; }

%for type, names in optional_queries.items():
constexpr std::array optional_${type} = {
%for name in names:
${name},
%endfor
};

template <> inline bool isQueryOptional(${type} query) {
return std::find(optional_${type}.begin(),
optional_${type}.end(),
query) != optional_${type}.end();
}

%endfor

}
20 changes: 12 additions & 8 deletions scripts/templates/tools-info.hpp.mako
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ namespace urinfo {
inline void printLoaderConfigInfos(${x}_loader_config_handle_t hLoaderConfig, std::string_view prefix = " ") {
%for etor in obj['etors']:
%if 'REFERENCE_COUNT' not in etor['name']:
std::cout << prefix;
printLoaderConfigInfo<${etor['desc'][1:etor['desc'].find(' ')-1].replace('$x', x)}>(hLoaderConfig, ${etor['name'].replace('$X', X)});
<%etype = th.etor_get_associated_type(n, tags, etor)
%>std::cout << prefix;
printLoaderConfigInfo<${etype}>(hLoaderConfig, ${etor['name'].replace('$X', X)});
%endif
%endfor
}
Expand All @@ -42,8 +43,9 @@ inline void printLoaderConfigInfos(${x}_loader_config_handle_t hLoaderConfig, st
inline void printAdapterInfos(${x}_adapter_handle_t hAdapter, std::string_view prefix = " ") {
%for etor in obj['etors']:
%if 'REFERENCE_COUNT' not in etor['name']:
std::cout << prefix;
printAdapterInfo<${etor['desc'][1:etor['desc'].find(' ')-1].replace('$x', x)}>(hAdapter, ${etor['name'].replace('$X', X)});
<%etype = th.etor_get_associated_type(n, tags, etor)
%>std::cout << prefix;
printAdapterInfo<${etype}>(hAdapter, ${etor['name'].replace('$X', X)});
%endif
%endfor
}
Expand All @@ -52,20 +54,22 @@ inline void printAdapterInfos(${x}_adapter_handle_t hAdapter, std::string_view p
%if obj["name"] == '$x_platform_info_t':
inline void printPlatformInfos(${x}_platform_handle_t hPlatform, std::string_view prefix = " ") {
%for etor in obj['etors']:
std::cout << prefix;
printPlatformInfo<${etor['desc'][1:etor['desc'].find(' ')-1].replace('$x', x)}>(hPlatform, ${etor['name'].replace('$X', X)});
<%etype = th.etor_get_associated_type(n, tags, etor)
%>std::cout << prefix;
printPlatformInfo<${etype}>(hPlatform, ${etor['name'].replace('$X', X)});
%endfor
}
%endif
%if obj['name'] == '$x_device_info_t':
inline void printDeviceInfos(${x}_device_handle_t hDevice, std::string_view prefix = " ") {
%for etor in obj['etors']:
std::cout << prefix;
<%etype = th.etor_get_associated_type(n, tags, etor)
%>std::cout << prefix;
%if etor['name'] == '$X_DEVICE_INFO_UUID':
printDeviceUUID(hDevice, ${etor['name'].replace('$X', X)});
%else:
printDeviceInfo<${etor['desc'][1:etor['desc'].find(' ')-1].replace('$x', x)}>(hDevice, ${etor['name'].replace('$X', X)});
printDeviceInfo<${etype}>(hDevice, ${etor['name'].replace('$X', X)});
%endif
%endfor
}
Expand Down
Loading

0 comments on commit 7470d9e

Please sign in to comment.