Skip to content

Commit

Permalink
Add support for static linking of the L0 adapter
Browse files Browse the repository at this point in the history
This patch adds a cmake option that builds the L0 adapter
as a static library and then embeds its in the loader.
The mechanim itself is fairly generic and, when a need arises,
the same can be done for other adapters.
  • Loading branch information
pbalcer committed Jul 15, 2024
1 parent a7920ef commit 1c95ae4
Show file tree
Hide file tree
Showing 40 changed files with 2,803 additions and 1,608 deletions.
7 changes: 6 additions & 1 deletion .github/workflows/build-hw-reusable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,18 @@ jobs:
strategy:
matrix:
adapter: [
{name: "${{inputs.name}}", platform: "${{inputs.platform}}"},
{name: "${{inputs.name}}", platform: "${{inputs.platform}}", static: OFF},
]
build_type: [Debug, Release]
compiler: [{c: gcc, cxx: g++}, {c: clang, cxx: clang++}]
# TODO: The latest L0 loader segfaults when built with clang.
exclude:
- adapter: {name: L0, platform: ""}
compiler: {c: clang, cxx: clang++}
include:
- adapter: {name: L0, platform: "", static: ON}
build_type: [Debug]
compiler: {c: gcc, cxx: g++}

runs-on: ${{matrix.adapter.name}}

Expand All @@ -63,6 +67,7 @@ jobs:
-DUR_DEVELOPER_MODE=ON
-DUR_BUILD_TESTS=ON
-DUR_BUILD_ADAPTER_${{matrix.adapter.name}}=ON
-DUR_STATIC_ADAPTER_${{matrix.adapter.name}}=${{matrix.adapter.static}}
-DUR_DPCXX=${{github.workspace}}/dpcpp_compiler/bin/clang++
-DUR_SYCL_LIBRARY_DIR=${{github.workspace}}/dpcpp_compiler/lib
${{ matrix.adapter.name == 'HIP' && '-DUR_CONFORMANCE_AMD_ARCH=gfx1030' || '' }}
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ option(UR_BUILD_ADAPTER_CUDA "Build the CUDA adapter" OFF)
option(UR_BUILD_ADAPTER_HIP "Build the HIP adapter" OFF)
option(UR_BUILD_ADAPTER_NATIVE_CPU "Build the Native-CPU adapter" OFF)
option(UR_BUILD_ADAPTER_ALL "Build all currently supported adapters" OFF)
option(UR_STATIC_ADAPTER_L0 "Build the Level-Zero adapter as static and embed in the loader" OFF)
option(UR_BUILD_EXAMPLE_CODEGEN "Build the codegen example." OFF)
option(VAL_USE_LIBBACKTRACE_BACKTRACE "enable libbacktrace validation backtrace for linux" OFF)
option(UR_ENABLE_ASSERTIONS "Enable assertions for all build types" OFF)
Expand Down
30 changes: 30 additions & 0 deletions scripts/generate_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,32 @@ def generate_loader(path, section, namespace, tags, version, specs, meta):
)
print("Generated %s lines of code.\n"%loc)

"""
generates c/c++ files from the specification documents
"""
def _mako_interface_loader_api(path, adapter, ext, namespace, tags, version, specs, meta):
dstpath = os.path.join(path, adapter)
os.makedirs(dstpath, exist_ok=True)

template = f"ur_interface_loader.{ext}.mako"
fin = os.path.join(templates_dir, template)

name = f"ur_interface_loader"

filename = f"{name}.{ext}"
fout = os.path.join(dstpath, filename)

print("Generating %s..."%fout)
return util.makoWrite(
fin, fout,
name=name,
adapter=adapter,
ver=version,
namespace=namespace,
tags=tags,
specs=specs,
meta=meta,)

"""
Entry-point:
generates adapter for unified_runtime
Expand All @@ -395,6 +421,10 @@ def generate_adapters(path, section, namespace, tags, version, specs, meta):
loc += _mako_linker_scripts(
dstpath, "adapter", "def", namespace, tags, version, specs, meta
)

loc += _mako_interface_loader_api(dstpath, "level_zero", "cpp", namespace, tags, version, specs, meta)
loc += _mako_interface_loader_api(dstpath, "level_zero", "hpp", namespace, tags, version, specs, meta)

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

"""
Expand Down
4 changes: 4 additions & 0 deletions scripts/templates/ldrddi.cpp.mako
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,10 @@ ${tbl['export']['name']}(
// Load the device-platform DDI tables
for( auto& platform : ur_loader::getContext()->platforms )
{
// statically linked adapter inside of the loader
if (platform.handle == nullptr)
continue;
if(platform.initStatus != ${X}_RESULT_SUCCESS)
continue;
auto getTable = reinterpret_cast<${tbl['pfn']}>(
Expand Down
4 changes: 3 additions & 1 deletion scripts/templates/queue_api.cpp.mako
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ from templates import helper as th
ur_queue_handle_t_::~ur_queue_handle_t_() {}

## FUNCTION ###################################################################
namespace ${x}::level_zero {
%for obj in th.get_queue_related_functions(specs, n, tags):
${X}_APIEXPORT ${x}_result_t ${X}_APICALL
${x}_result_t
${th.make_func_name(n, tags, obj)}(
%for line in th.make_param_lines(n, tags, obj, format=["name", "type", "delim"]):
${line}
Expand All @@ -35,3 +36,4 @@ ${th.make_func_name(n, tags, obj)}(
return ${obj['params'][0]['name']}->${th.transform_queue_related_function_name(n, tags, obj, format=["name"])};
}
%endfor
}
88 changes: 88 additions & 0 deletions scripts/templates/ur_interface_loader.cpp.mako
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<%!
import re
from templates import helper as th
%><%
n=namespace
N=n.upper()
x=tags['$x']
X=x.upper()
Adapter=adapter.upper()
%>//===--------- ${n}_interface_loader.cpp - Level Zero Adapter ------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include <${n}_api.h>
#include <${n}_ddi.h>

#include "ur_interface_loader.hpp"

static ur_result_t validateProcInputs(ur_api_version_t version, void *pDdiTable) {
if (nullptr == pDdiTable) {
return UR_RESULT_ERROR_INVALID_NULL_POINTER;
}
// Pre 1.0 we enforce loader and adapter must have same version.
// Post 1.0 only major version match should be required.
if (version != UR_API_VERSION_CURRENT) {
return UR_RESULT_ERROR_UNSUPPORTED_VERSION;
}
return UR_RESULT_SUCCESS;
}

#ifdef UR_STATIC_ADAPTER_${Adapter}
namespace ${n}::${adapter} {
#elif defined(__cplusplus)
extern "C" {
#endif

%for tbl in th.get_pfntables(specs, meta, n, tags):
${X}_APIEXPORT ${x}_result_t ${X}_APICALL ${tbl['export']['name']}(
%for line in th.make_param_lines(n, tags, tbl['export'], format=["type", "name", "delim"]):
${line}
%endfor
)
{
auto result = validateProcInputs(version, pDdiTable);
if (UR_RESULT_SUCCESS != result) {
return result;
}

%for obj in tbl['functions']:
pDdiTable->${th.append_ws(th.make_pfn_name(n, tags, obj), 43)} = ${n}::${adapter}::${th.make_func_name(n, tags, obj)};
%endfor

return result;
}

%endfor

#ifdef UR_STATIC_ADAPTER_${Adapter}
} // namespace ur::${adapter}
#elif defined(__cplusplus)
} // extern "C"
#endif

#ifdef UR_STATIC_ADAPTER_${Adapter}
namespace ur::${adapter} {
ur_result_t urAdapterGetDdiTables(ur_dditable_t *ddi) {
if (ddi == nullptr) {
return UR_RESULT_ERROR_INVALID_NULL_POINTER;
}

ur_result_t result;

%for tbl in th.get_pfntables(specs, meta, n, tags):
result = ${n}::${adapter}::${tbl['export']['name']}( ${X}_API_VERSION_CURRENT, &ddi->${tbl['name']} );
if (result != UR_RESULT_SUCCESS)
return result;
%endfor

return result;
}
}
#endif
38 changes: 38 additions & 0 deletions scripts/templates/ur_interface_loader.hpp.mako
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<%!
import re
from templates import helper as th
%><%
n=namespace
N=n.upper()
x=tags['$x']
X=x.upper()
Adapter=adapter.upper()
%>//===--------- ${n}_interface_loader.hpp - Level Zero Adapter ------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include <${n}_api.h>
#include <${n}_ddi.h>

namespace ${n}::${adapter} {
%for s in specs:
%for obj in th.filter_items(s['objects'], 'type', 'function'):
%if not th.obj_traits.is_loader_only(obj):
${x}_result_t ${th.make_func_name(n, tags, obj)}(
%for line in th.make_param_lines(n, tags, obj, format=["type", "name", "delim"]):
${line}
%endfor
);
%endif
%endfor
%endfor
#ifdef UR_STATIC_ADAPTER_LEVEL_ZERO
ur_result_t urAdapterGetDdiTables(ur_dditable_t *ddi);
#endif
}
12 changes: 10 additions & 2 deletions source/adapters/level_zero/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,12 @@ target_include_directories(LevelZeroLoader-Headers
INTERFACE "${LEVEL_ZERO_INCLUDE_DIR}"
)

add_ur_adapter(${TARGET_NAME}
SHARED
set(ADAPTER_LIB_TYPE SHARED)
if(UR_STATIC_ADAPTER_L0)
set(ADAPTER_LIB_TYPE STATIC)
endif()

add_ur_adapter(${TARGET_NAME} ${ADAPTER_LIB_TYPE}
${CMAKE_CURRENT_SOURCE_DIR}/ur_interface_loader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/adapter.hpp
${CMAKE_CURRENT_SOURCE_DIR}/adapter.cpp
Expand Down Expand Up @@ -137,6 +141,10 @@ add_ur_adapter(${TARGET_NAME}
${CMAKE_CURRENT_SOURCE_DIR}/v2/queue_immediate_in_order.cpp
)

if(UR_STATIC_ADAPTER_L0)
target_compile_definitions(ur_adapter_level_zero PUBLIC UR_STATIC_ADAPTER_LEVEL_ZERO)
endif()

if(NOT WIN32)
target_sources(ur_adapter_level_zero
PRIVATE
Expand Down
18 changes: 9 additions & 9 deletions source/adapters/level_zero/adapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,8 @@ ur_result_t adapterStateTeardown() {
return UR_RESULT_SUCCESS;
}

UR_APIEXPORT ur_result_t UR_APICALL urAdapterGet(
namespace ur::level_zero {
ur_result_t urAdapterGet(
uint32_t NumEntries, ///< [in] the number of platforms to be added to
///< phAdapters. If phAdapters is not NULL, then
///< NumEntries should be greater than zero, otherwise
Expand Down Expand Up @@ -281,7 +282,7 @@ UR_APIEXPORT ur_result_t UR_APICALL urAdapterGet(
return UR_RESULT_SUCCESS;
}

UR_APIEXPORT ur_result_t UR_APICALL urAdapterRelease(ur_adapter_handle_t) {
ur_result_t urAdapterRelease(ur_adapter_handle_t) {
// Check first if the Adapter pointer is valid
if (GlobalAdapter) {
std::lock_guard<std::mutex> Lock{GlobalAdapter->Mutex};
Expand All @@ -293,7 +294,7 @@ UR_APIEXPORT ur_result_t UR_APICALL urAdapterRelease(ur_adapter_handle_t) {
return UR_RESULT_SUCCESS;
}

UR_APIEXPORT ur_result_t UR_APICALL urAdapterRetain(ur_adapter_handle_t) {
ur_result_t urAdapterRetain(ur_adapter_handle_t) {
if (GlobalAdapter) {
std::lock_guard<std::mutex> Lock{GlobalAdapter->Mutex};
GlobalAdapter->RefCount++;
Expand All @@ -302,7 +303,7 @@ UR_APIEXPORT ur_result_t UR_APICALL urAdapterRetain(ur_adapter_handle_t) {
return UR_RESULT_SUCCESS;
}

UR_APIEXPORT ur_result_t UR_APICALL urAdapterGetLastError(
ur_result_t urAdapterGetLastError(
ur_adapter_handle_t, ///< [in] handle of the platform instance
const char **Message, ///< [out] pointer to a C string where the adapter
///< specific error message will be stored.
Expand All @@ -315,11 +316,9 @@ UR_APIEXPORT ur_result_t UR_APICALL urAdapterGetLastError(
return ErrorMessageCode;
}

UR_APIEXPORT ur_result_t UR_APICALL urAdapterGetInfo(ur_adapter_handle_t,
ur_adapter_info_t PropName,
size_t PropSize,
void *PropValue,
size_t *PropSizeRet) {
ur_result_t urAdapterGetInfo(ur_adapter_handle_t, ur_adapter_info_t PropName,
size_t PropSize, void *PropValue,
size_t *PropSizeRet) {
UrReturnHelper ReturnValue(PropSize, PropValue, PropSizeRet);

switch (PropName) {
Expand All @@ -333,3 +332,4 @@ UR_APIEXPORT ur_result_t UR_APICALL urAdapterGetInfo(ur_adapter_handle_t,

return UR_RESULT_SUCCESS;
}
} // namespace ur::level_zero
Loading

0 comments on commit 1c95ae4

Please sign in to comment.