Skip to content

Commit

Permalink
[L0] Make all API functions operating on queue virtual
Browse files Browse the repository at this point in the history
`ur_queue_handle_t_` is now an abstract class and both legacy and the
new, optimized queue variants are expected to inherit from it
and implement all the virtual methods.

API functions that operate on queue, are auto-generated and now they
only invoke virtual function on the queue.
  • Loading branch information
igchor committed Jul 2, 2024
1 parent aaf0810 commit e6dc6d9
Show file tree
Hide file tree
Showing 18 changed files with 1,764 additions and 268 deletions.
43 changes: 43 additions & 0 deletions scripts/generate_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -454,3 +454,46 @@ def generate_tools(path, section, namespace, tags, version, specs, meta):
loc += _mako_info_hpp(infodir, namespace, tags, version, specs, meta)

print("TOOLS Generated %s lines of code.\n" % loc)

"""
Entry-point:
generates API functions that accept queue for level_zero
"""
def generate_level_zero_queue_api(path, section, namespace, tags, version, specs, meta):
template = "queue_api.cpp.mako"
fin = os.path.join("templates", template)

name = "queue_api"
filename = "queue_api.cpp"
layer_dstpath = os.path.join(path, "adapters/level_zero")
os.makedirs(layer_dstpath, exist_ok=True)
fout = os.path.join(layer_dstpath, filename)

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

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

template = "queue_api.hpp.mako"
fin = os.path.join("templates", template)

filename = "queue_api.hpp"
fout = os.path.join(layer_dstpath, filename)

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

loc += util.makoWrite(
fin, fout,
ver=version,
name = name,
namespace=namespace,
tags=tags,
specs=specs,
meta=meta)
print("QUEUE Generated %s lines of code.\n" % loc)
3 changes: 3 additions & 0 deletions scripts/json2src.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def add_argument(parser, name, help, default=False):
add_argument(parser, "adapters", "generation of null adapter files.", True)
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)
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 Down Expand Up @@ -60,6 +61,8 @@ def add_argument(parser, name, help, default=False):
generate_code.generate_common(srcpath, config['name'], config['namespace'], config['tags'], args.ver, specs, input['meta'])
if args.tools:
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.debug:
util.makoFileListWrite("generated.json")
Expand Down
32 changes: 32 additions & 0 deletions scripts/templates/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -1604,3 +1604,35 @@ def get_handle_create_get_retain_release_functions(specs, namespace, tags):
records.append(record)

return records

"""
Public:
returns a list of objects representing functions that accept $x_queue_handle_t as a first param
"""
def get_queue_related_functions(specs, namespace, tags):
funcs = []
for s in specs:
for obj in s['objects']:
if re.match(r"function", obj['type']):
if obj['params'] and obj['params'][0]['type'] == '$x_queue_handle_t':
funcs.append(obj)
return funcs

"""
Public:
transform a queue related function using following rules:
- remove $x prefix
- make first letter lowercase
- remove first param (queue)
"""
def transform_queue_related_function_name(namespace, tags, obj, format = ["name", "type"]):
function_name = make_func_name(namespace, tags, obj).replace(namespace,'')
function_name=function_name[0].lower() + function_name[1:]

if obj['params'][0]['type'] != '$x_queue_handle_t':
raise ValueError('First parameter is not a queue handle')

params = make_param_lines(namespace, tags, obj, format=format)
params = params[1:]

return "{}({})".format(function_name, ", ".join(params))
37 changes: 37 additions & 0 deletions scripts/templates/queue_api.cpp.mako
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<%!
import re
from templates import helper as th
%><%
n=namespace
N=n.upper()
x=tags['$x']
X=x.upper()
%>/*
*
* 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 ${name}.cpp
*
*/

#include "queue_api.hpp"

ur_queue_handle_t_::~ur_queue_handle_t_() {}

## FUNCTION ###################################################################
%for obj in th.get_queue_related_functions(specs, n, tags):
${X}_APIEXPORT ${x}_result_t ${X}_APICALL
${th.make_func_name(n, tags, obj)}(
%for line in th.make_param_lines(n, tags, obj, format=["name", "type", "delim"]):
${line}
%endfor
)
{
return ${obj['params'][0]['name']}->${th.transform_queue_related_function_name(n, tags, obj, format=["name"])};
}
%endfor
31 changes: 31 additions & 0 deletions scripts/templates/queue_api.hpp.mako
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<%!
import re
from templates import helper as th
%><%
n=namespace
N=n.upper()
x=tags['$x']
X=x.upper()
%>/*
*
* 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 ${name}.hpp
*
*/

#pragma once

#include <ur_api.h>

struct ur_queue_handle_t_ {
virtual ~ur_queue_handle_t_();
%for obj in th.get_queue_related_functions(specs, n, tags):
virtual ${x}_result_t ${th.transform_queue_related_function_name(n, tags, obj, format=["type"])} = 0;
%endfor
};
5 changes: 5 additions & 0 deletions source/adapters/level_zero/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,11 @@ add_ur_adapter(${TARGET_NAME}
${CMAKE_CURRENT_SOURCE_DIR}/physical_mem.hpp
${CMAKE_CURRENT_SOURCE_DIR}/platform.hpp
${CMAKE_CURRENT_SOURCE_DIR}/program.hpp
${CMAKE_CURRENT_SOURCE_DIR}/queue_api.hpp
${CMAKE_CURRENT_SOURCE_DIR}/queue.hpp
${CMAKE_CURRENT_SOURCE_DIR}/sampler.hpp
${CMAKE_CURRENT_SOURCE_DIR}/v2/queue_immediate_in_order.hpp
${CMAKE_CURRENT_SOURCE_DIR}/v2/queue_factory.hpp
${CMAKE_CURRENT_SOURCE_DIR}/ur_level_zero.cpp
${CMAKE_CURRENT_SOURCE_DIR}/common.cpp
${CMAKE_CURRENT_SOURCE_DIR}/context.cpp
Expand All @@ -126,10 +129,12 @@ add_ur_adapter(${TARGET_NAME}
${CMAKE_CURRENT_SOURCE_DIR}/physical_mem.cpp
${CMAKE_CURRENT_SOURCE_DIR}/platform.cpp
${CMAKE_CURRENT_SOURCE_DIR}/program.cpp
${CMAKE_CURRENT_SOURCE_DIR}/queue_api.cpp
${CMAKE_CURRENT_SOURCE_DIR}/queue.cpp
${CMAKE_CURRENT_SOURCE_DIR}/sampler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/image.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../../ur/ur.cpp
${CMAKE_CURRENT_SOURCE_DIR}/v2/queue_immediate_in_order.cpp
)

if(NOT WIN32)
Expand Down
11 changes: 6 additions & 5 deletions source/adapters/level_zero/enqueue_native.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@

#include <ur_api.h>

UR_APIEXPORT ur_result_t UR_APICALL urEnqueueNativeCommandExp(
ur_queue_handle_t, ur_exp_enqueue_native_command_function_t, void *,
uint32_t, const ur_mem_handle_t *,
const ur_exp_enqueue_native_command_properties_t *, uint32_t,
const ur_event_handle_t *, ur_event_handle_t *) {
#include "queue.hpp"

ur_result_t ur_queue_handle_legacy_t_::enqueueNativeCommandExp(
ur_exp_enqueue_native_command_function_t, void *, uint32_t,
const ur_mem_handle_t *, const ur_exp_enqueue_native_command_properties_t *,
uint32_t, const ur_event_handle_t *, ur_event_handle_t *) {
return UR_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
23 changes: 11 additions & 12 deletions source/adapters/level_zero/event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ bool WaitListEmptyOrAllEventsFromSameQueue(
return true;
}

UR_APIEXPORT ur_result_t UR_APICALL urEnqueueEventsWait(
ur_queue_handle_t UrQueue, ///< [in] handle of the queue object
ur_result_t ur_queue_handle_legacy_t_::enqueueEventsWait( ///< [in] handle of
///< the queue object
uint32_t NumEventsInWaitList, ///< [in] size of the event wait list
const ur_event_handle_t
*EventWaitList, ///< [in][optional][range(0, numEventsInWaitList)]
Expand All @@ -72,7 +72,7 @@ UR_APIEXPORT ur_result_t UR_APICALL urEnqueueEventsWait(
*OutEvent ///< [in,out][optional] return an event object that identifies
///< this particular command instance.
) {
auto Queue = Legacy(UrQueue);
auto Queue = this;
if (EventWaitList) {
bool UseCopyEngine = false;

Expand Down Expand Up @@ -152,8 +152,9 @@ static const bool InOrderBarrierBySignal = [] {
return (UrRet ? std::atoi(UrRet) : true);
}();

UR_APIEXPORT ur_result_t UR_APICALL urEnqueueEventsWaitWithBarrier(
ur_queue_handle_t UrQueue, ///< [in] handle of the queue object
ur_result_t
ur_queue_handle_legacy_t_::enqueueEventsWaitWithBarrier( ///< [in] handle of the
///< queue object
uint32_t NumEventsInWaitList, ///< [in] size of the event wait list
const ur_event_handle_t
*EventWaitList, ///< [in][optional][range(0, numEventsInWaitList)]
Expand All @@ -165,7 +166,7 @@ UR_APIEXPORT ur_result_t UR_APICALL urEnqueueEventsWaitWithBarrier(
*OutEvent ///< [in,out][optional] return an event object that identifies
///< this particular command instance.
) {
auto Queue = Legacy(UrQueue);
auto Queue = this;

// Lock automatically releases when this goes out of scope.
std::scoped_lock<ur_shared_mutex> lock(Queue->Mutex);
Expand Down Expand Up @@ -661,8 +662,7 @@ UR_APIEXPORT ur_result_t UR_APICALL urEventGetProfilingInfo(
return UR_RESULT_SUCCESS;
}

UR_APIEXPORT ur_result_t UR_APICALL urEnqueueTimestampRecordingExp(
ur_queue_handle_t UrQueue, ///< [in] handle of the queue object
ur_result_t ur_queue_handle_legacy_t_::enqueueTimestampRecordingExp(
bool Blocking, ///< [in] blocking or non-blocking enqueue
uint32_t NumEventsInWaitList, ///< [in] size of the event wait list
const ur_event_handle_t
Expand All @@ -676,7 +676,7 @@ UR_APIEXPORT ur_result_t UR_APICALL urEnqueueTimestampRecordingExp(
*OutEvent ///< [in,out] return an event object that identifies
///< this particular command instance.
) {
auto Queue = Legacy(UrQueue);
auto Queue = this;
// Lock automatically releases when this goes out of scope.
std::scoped_lock<ur_shared_mutex> lock(Queue->Mutex);

Expand Down Expand Up @@ -1022,7 +1022,6 @@ ur_result_t urEventReleaseInternal(ur_event_handle_t Event) {

// Save pointer to the queue before deleting/resetting event.
auto Queue = Legacy(Event->UrQueue);
auto URQueue = Event->UrQueue;

// If the event was a timestamp recording, we try to evict its entry in the
// queue.
Expand Down Expand Up @@ -1054,8 +1053,8 @@ ur_result_t urEventReleaseInternal(ur_event_handle_t Event) {
// created so that we can avoid ur_queue_handle_t is released before the
// associated ur_event_handle_t is released. Here we have to decrement it so
// ur_queue_handle_t can be released successfully.
if (URQueue) {
UR_CALL(urQueueReleaseInternal(URQueue));
if (Queue) {
UR_CALL(urQueueReleaseInternal(Queue));
}

return UR_RESULT_SUCCESS;
Expand Down
30 changes: 14 additions & 16 deletions source/adapters/level_zero/image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -748,14 +748,14 @@ UR_APIEXPORT ur_result_t UR_APICALL urBindlessImagesSampledImageCreateExp(
return UR_RESULT_SUCCESS;
}

UR_APIEXPORT ur_result_t UR_APICALL urBindlessImagesImageCopyExp(
ur_queue_handle_t hUrQueue, void *pDst, void *pSrc,
const ur_image_format_t *pImageFormat, const ur_image_desc_t *pImageDesc,
ur_exp_image_copy_flags_t imageCopyFlags, ur_rect_offset_t srcOffset,
ur_rect_offset_t dstOffset, ur_rect_region_t copyExtent,
ur_rect_region_t hostExtent, uint32_t numEventsInWaitList,
const ur_event_handle_t *phEventWaitList, ur_event_handle_t *phEvent) {
auto hQueue = Legacy(hUrQueue);
ur_result_t ur_queue_handle_legacy_t_::bindlessImagesImageCopyExp(
void *pDst, void *pSrc, const ur_image_format_t *pImageFormat,
const ur_image_desc_t *pImageDesc, ur_exp_image_copy_flags_t imageCopyFlags,
ur_rect_offset_t srcOffset, ur_rect_offset_t dstOffset,
ur_rect_region_t copyExtent, ur_rect_region_t hostExtent,
uint32_t numEventsInWaitList, const ur_event_handle_t *phEventWaitList,
ur_event_handle_t *phEvent) {
auto hQueue = this;
std::scoped_lock<ur_shared_mutex> Lock(hQueue->Mutex);

UR_ASSERT(hQueue, UR_RESULT_ERROR_INVALID_NULL_HANDLE);
Expand Down Expand Up @@ -1028,11 +1028,10 @@ UR_APIEXPORT ur_result_t UR_APICALL urBindlessImagesDestroyExternalSemaphoreExp(
return UR_RESULT_ERROR_UNSUPPORTED_FEATURE;
}

UR_APIEXPORT ur_result_t UR_APICALL urBindlessImagesWaitExternalSemaphoreExp(
ur_queue_handle_t hQueue, ur_exp_interop_semaphore_handle_t hSemaphore,
bool hasValue, uint64_t waitValue, uint32_t numEventsInWaitList,
ur_result_t ur_queue_handle_legacy_t_::bindlessImagesWaitExternalSemaphoreExp(
ur_exp_interop_semaphore_handle_t hSemaphore, bool hasValue,
uint64_t waitValue, uint32_t numEventsInWaitList,
const ur_event_handle_t *phEventWaitList, ur_event_handle_t *phEvent) {
std::ignore = hQueue;
std::ignore = hSemaphore;
std::ignore = hasValue;
std::ignore = waitValue;
Expand All @@ -1044,11 +1043,10 @@ UR_APIEXPORT ur_result_t UR_APICALL urBindlessImagesWaitExternalSemaphoreExp(
return UR_RESULT_ERROR_UNSUPPORTED_FEATURE;
}

UR_APIEXPORT ur_result_t UR_APICALL urBindlessImagesSignalExternalSemaphoreExp(
ur_queue_handle_t hQueue, ur_exp_interop_semaphore_handle_t hSemaphore,
bool hasValue, uint64_t signalValue, uint32_t numEventsInWaitList,
ur_result_t ur_queue_handle_legacy_t_::bindlessImagesSignalExternalSemaphoreExp(
ur_exp_interop_semaphore_handle_t hSemaphore, bool hasValue,
uint64_t signalValue, uint32_t numEventsInWaitList,
const ur_event_handle_t *phEventWaitList, ur_event_handle_t *phEvent) {
std::ignore = hQueue;
std::ignore = hSemaphore;
std::ignore = hasValue;
std::ignore = signalValue;
Expand Down
Loading

0 comments on commit e6dc6d9

Please sign in to comment.