Skip to content

Commit 40d1aac

Browse files
committed
DDI extension support
- Support in the L0 Loader for https://oneapi-src.github.io/level-zero-spec/level-zero/latest/core/EXT_Driver_DDIHandles.html#ze-extension-driver-ddi-handles - To improve the speed for each call of L0 apis into the correct driver, the new support enables for the driver to allocate a header that stores that driver's ddi tables such that the Loader does not need to perform translation of handles to/from ze_object_t. - Given a driver supports the new extension, the loader will no longer create the ze_object_t and instead use the packed ddi tables in each handle_t. - The code has been refactored such that the legacy path will continue to work for the driver that has not converted over without interfering with a driver which now uses the "fast" path. - This new code path also removes the need for handle translation by the user if the drivers all support the new extension. Signed-off-by: Neil R. Spruit <neil.r.spruit@intel.com>
1 parent 3c938e2 commit 40d1aac

26 files changed

Lines changed: 20588 additions & 5214 deletions

samples/zello_world/zello_world.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,9 @@ int main( int argc, char *argv[] )
131131

132132
for( uint32_t driver = 0; driver < driverCount; ++driver )
133133
{
134+
std::cout << "Driver # " << driver << "\n";
134135
pDriver = drivers[driver];
135136
pDevice = findDevice( pDriver, type );
136-
if( pDevice )
137-
{
138-
break;
139-
}
140137
}
141138
}
142139

scripts/generate_code.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,23 @@ def _mako_loader_cpp(path, namespace, tags, version, specs, meta):
141141
filename = "%s.cpp"%(name)
142142
fout = os.path.join(path, filename)
143143

144+
print("Generating %s..."%fout)
145+
loc += util.makoWrite(
146+
fin, fout,
147+
name=name,
148+
ver=version,
149+
namespace=namespace,
150+
tags=tags,
151+
specs=specs,
152+
meta=meta)
153+
154+
template = "ldrddi_legacy.cpp.mako"
155+
fin = os.path.join(templates_dir, template)
156+
157+
name = "%s_ldrddi_legacy"%(namespace)
158+
filename = "%s.cpp"%(name)
159+
fout = os.path.join(path, filename)
160+
144161
print("Generating %s..."%fout)
145162
loc += util.makoWrite(
146163
fin, fout,

scripts/templates/helper.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1702,6 +1702,43 @@ def get_class_function_objs(specs, cname, minVersion = 0, maxVersion = 9999):
17021702
objects.append(obj)
17031703
return sorted(objects, key=lambda obj: (float(obj.get('version',"1.0"))*10000) + int(obj.get('ordinal',"100")))
17041704

1705+
"""
1706+
Public:
1707+
returns the version of a function object
1708+
"""
1709+
def get_version(obj):
1710+
if obj_traits.is_function(obj):
1711+
ret_version = "ZE_API_VERSION_FORCE_UINT32"
1712+
version = obj.get('version')
1713+
if version == "1.0":
1714+
ret_version = "ZE_API_VERSION_1_0"
1715+
if version == "1.1":
1716+
ret_version = "ZE_API_VERSION_1_1"
1717+
if version == "1.2":
1718+
ret_version = "ZE_API_VERSION_1_2"
1719+
if version == "1.3":
1720+
ret_version = "ZE_API_VERSION_1_3"
1721+
if version == "1.4":
1722+
ret_version = "ZE_API_VERSION_1_4"
1723+
if version == "1.5":
1724+
ret_version = "ZE_API_VERSION_1_5"
1725+
if version == "1.6":
1726+
ret_version = "ZE_API_VERSION_1_6"
1727+
if version == "1.7":
1728+
ret_version = "ZE_API_VERSION_1_7"
1729+
if version == "1.8":
1730+
ret_version = "ZE_API_VERSION_1_8"
1731+
if version == "1.9":
1732+
ret_version = "ZE_API_VERSION_1_9"
1733+
if version == "1.10":
1734+
ret_version = "ZE_API_VERSION_1_10"
1735+
if version == "1.11":
1736+
ret_version = "ZE_API_VERSION_1_11"
1737+
if version == "1.12":
1738+
ret_version = "ZE_API_VERSION_1_12"
1739+
assert(ret_version != "ZE_API_VERSION_FORCE_UINT32")
1740+
return ret_version
1741+
17051742
"""
17061743
Public:
17071744
returns a list of all non-experimental function objs and a list of experimental function objs for the specified class

scripts/templates/ldrddi.cpp.mako

Lines changed: 71 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,28 @@ namespace loader
138138
{
139139
for( uint32_t i = 0; i < library_driver_handle_count; ++i ) {
140140
uint32_t driver_index = total_driver_handle_count + i;
141-
${obj['params'][1]['name']}[ driver_index ] = reinterpret_cast<${n}_driver_handle_t>(
142-
context->${n}_driver_factory.getInstance( ${obj['params'][1]['name']}[ driver_index ], &drv.dditable ) );
141+
if (drv.driverDDIHandleSupportQueried == false) {
142+
drv.properties = {};
143+
drv.properties.stype = ZE_STRUCTURE_TYPE_DRIVER_DDI_HANDLES_EXT_PROPERTIES;
144+
drv.properties.pNext = nullptr;
145+
ze_driver_properties_t driverProperties = {};
146+
driverProperties.stype = ZE_STRUCTURE_TYPE_DRIVER_PROPERTIES;
147+
driverProperties.pNext = nullptr;
148+
driverProperties.pNext = &drv.properties;
149+
ze_result_t res = drv.dditable.ze.Driver.pfnGetProperties(${obj['params'][1]['name']}[ driver_index ], &driverProperties);
150+
if (res != ZE_RESULT_SUCCESS) {
151+
if (loader::context->debugTraceEnabled) {
152+
std::string message = drv.name + " failed zeDriverGetProperties query, returned ";
153+
loader::context->debug_trace_message(message, loader::to_string(res));
154+
}
155+
return res;
156+
}
157+
drv.driverDDIHandleSupportQueried = true;
158+
}
159+
if (!(drv.properties.flags & ZE_DRIVER_DDI_HANDLE_EXT_FLAG_DDI_HANDLE_EXT_SUPPORTED)) {
160+
${obj['params'][1]['name']}[ driver_index ] = reinterpret_cast<${n}_driver_handle_t>(
161+
context->${n}_driver_factory.getInstance( ${obj['params'][1]['name']}[ driver_index ], &drv.dditable ) );
162+
}
143163
}
144164
}
145165
catch( std::bad_alloc& )
@@ -161,167 +181,62 @@ namespace loader
161181
%else:
162182
%for i, item in enumerate(th.get_loader_prologue(n, tags, obj, meta)):
163183
%if 0 == i:
164-
// extract driver's function pointer table
184+
// extract handle's function pointer table
165185
%if 'range' in item:
166-
auto dditable = reinterpret_cast<${item['obj']}*>( ${item['name']}[ 0 ] )->dditable;
167-
%else:
168-
auto dditable = reinterpret_cast<${item['obj']}*>( ${item['name']} )->dditable;
169-
%endif
170-
auto ${th.make_pfn_name(n, tags, obj)} = dditable->${n}.${th.get_table_name(n, tags, obj)}.${th.make_pfn_name(n, tags, obj)};
171-
if( nullptr == ${th.make_pfn_name(n, tags, obj)} )
172-
return ${X}_RESULT_ERROR_UNINITIALIZED;
173-
186+
%if namespace == "ze":
187+
auto dditable = reinterpret_cast<ze_handle_t*>( ${item['name']}[ 0 ] )->pCore;
188+
%elif namespace == "zet":
189+
auto dditable = reinterpret_cast<ze_handle_t*>( ${item['name']}[ 0 ] )->pTools;
190+
%elif namespace == "zes":
191+
auto dditable = reinterpret_cast<ze_handle_t*>( ${item['name']}[ 0 ] )->pSysman;
174192
%endif
175-
%if 'range' in item:
176-
<%
177-
add_local = True%>// convert loader handles to driver handles
178-
auto ${item['name']}Local = new ${item['type']} [${item['range'][1]}];
179-
<%
180-
arrays_to_delete.append(item['name']+ 'Local')
181-
%>for( size_t i = ${item['range'][0]}; ( nullptr != ${item['name']} ) && ( i < ${item['range'][1]} ); ++i )
182-
${item['name']}Local[ i ] = reinterpret_cast<${item['obj']}*>( ${item['name']}[ i ] )->handle;
183-
%else:
184-
%if item['optional']:
185-
// convert loader handle to driver handle
186-
${item['name']} = ( ${item['name']} ) ? reinterpret_cast<${item['obj']}*>( ${item['name']} )->handle : nullptr;
187193
%else:
188-
%if re.match(r"\w+ImageDestroy$", th.make_func_name(n, tags, obj)):
189-
// remove the handle from the kernel arugment map
190-
{
191-
std::lock_guard<std::mutex> lock(context->image_handle_map_lock);
192-
context->image_handle_map.erase(reinterpret_cast<ze_image_object_t*>(hImage));
193-
}
194+
%if namespace == "ze":
195+
auto dditable = reinterpret_cast<ze_handle_t*>( ${item['name']} )->pCore;
196+
%elif namespace == "zet":
197+
auto dditable = reinterpret_cast<ze_handle_t*>( ${item['name']} )->pTools;
198+
%elif namespace == "zes":
199+
auto dditable = reinterpret_cast<ze_handle_t*>( ${item['name']} )->pSysman;
194200
%endif
195-
%if re.match(r"\w+SamplerDestroy$", th.make_func_name(n, tags, obj)):
196-
// remove the handle from the kernel arugment map
197-
{
198-
std::lock_guard<std::mutex> lock(context->sampler_handle_map_lock);
199-
context->sampler_handle_map.erase(reinterpret_cast<ze_sampler_object_t*>(hSampler));
200-
}
201-
%endif
202-
// convert loader handle to driver handle
203-
${item['name']} = reinterpret_cast<${item['obj']}*>( ${item['name']} )->handle;
204201
%endif
205-
%endif
206-
207-
%endfor
208-
%if re.match(r"\w+KernelSetArgumentValue$", th.make_func_name(n, tags, obj)):
209-
// convert pArgValue to correct handle if applicable
210-
void *internalArgValue = const_cast<void *>(pArgValue);
211-
if (pArgValue) {
212-
// check if the arg value is a translated handle
213-
ze_image_object_t **imageHandle = static_cast<ze_image_object_t **>(internalArgValue);
214-
ze_sampler_object_t **samplerHandle = static_cast<ze_sampler_object_t **>(internalArgValue);
215-
{
216-
std::lock_guard<std::mutex> image_lock(context->image_handle_map_lock);
217-
std::lock_guard<std::mutex> sampler_lock(context->sampler_handle_map_lock);
218-
if( context->image_handle_map.find(*imageHandle) != context->image_handle_map.end() ) {
219-
internalArgValue = &context->image_handle_map[*imageHandle];
220-
} else if( context->sampler_handle_map.find(*samplerHandle) != context->sampler_handle_map.end() ) {
221-
internalArgValue = &context->sampler_handle_map[*samplerHandle];
222-
}
223-
}
202+
if (dditable->isValidFlag == 0)
203+
return ${X}_RESULT_ERROR_UNINITIALIZED;
204+
// Check that api version in the driver is supported by this version of the API
205+
if (dditable->version < ${th.get_version(obj)}) {
206+
return ${X}_RESULT_ERROR_UNSUPPORTED_VERSION;
224207
}
208+
auto ${th.make_pfn_name(n, tags, obj)} = dditable->${th.get_table_name(n, tags, obj)}->${th.make_pfn_name(n, tags, obj)};
209+
if( nullptr == ${th.make_pfn_name(n, tags, obj)} )
210+
return ${X}_RESULT_ERROR_UNINITIALIZED;
225211
%endif
226-
## Workaround due to incorrect defintion of phWaitEvents in the ze headers which missed the range values.
227-
## To be removed once the headers have been updated in a new spec release.
228-
%if re.match(r"\w+CommandListAppendMetricQueryEnd$", th.make_func_name(n, tags, obj)):
229-
// convert loader handles to driver handles
230-
auto phWaitEventsLocal = new ze_event_handle_t [numWaitEvents];
231-
for( size_t i = 0; ( nullptr != phWaitEvents ) && ( i < numWaitEvents ); ++i )
232-
phWaitEventsLocal[ i ] = reinterpret_cast<ze_event_object_t*>( phWaitEvents[ i ] )->handle;
233-
234-
// forward to device-driver
235-
result = pfnAppendMetricQueryEnd( hCommandList, hMetricQuery, hSignalEvent, numWaitEvents, phWaitEventsLocal );
236-
delete []phWaitEventsLocal;
237-
%else:
238-
// forward to device-driver
239-
%if add_local:
240-
result = ${th.make_pfn_name(n, tags, obj)}( ${", ".join(th.make_param_lines(n, tags, obj, format=["name", "local"]))} );
241-
%for array_name in arrays_to_delete:
242-
delete []${array_name};
243212
%endfor
244-
%else:
245-
%if re.match(r"\w+KernelSetArgumentValue$", th.make_func_name(n, tags, obj)):
246-
result = pfnSetArgumentValue( hKernel, argIndex, argSize, const_cast<const void *>(internalArgValue) );
247-
%else:
213+
// forward to device-driver
248214
result = ${th.make_pfn_name(n, tags, obj)}( ${", ".join(th.make_param_lines(n, tags, obj, format=["name"]))} );
249-
%endif
250-
%endif
251-
%endif
252-
<%
253-
del arrays_to_delete
254-
del add_local%>
255-
%for i, item in enumerate(th.get_loader_epilogue(n, tags, obj, meta)):
256-
%if 0 == i:
257-
%if not re.match(r"\w+ModuleDynamicLink$", th.make_func_name(n, tags, obj)) and not re.match(r"\w+ModuleCreate$", th.make_func_name(n, tags, obj)):
258-
if( ${X}_RESULT_SUCCESS != result )
259-
return result;
260-
261-
%endif
262-
%endif
263-
%if item['release']:
264-
// release loader handle
265-
context->${item['factory']}.release( ${item['name']} );
266-
%else:
267-
try
268-
{
269-
%if 'range' in item:
270-
// convert driver handles to loader handles
271-
for( size_t i = ${item['range'][0]}; ( nullptr != ${item['name']} ) && ( i < ${item['range'][1]} ); ++i )
272-
${item['name']}[ i ] = reinterpret_cast<${item['type']}>(
273-
context->${item['factory']}.getInstance( ${item['name']}[ i ], dditable ) );
274-
%else:
275-
// convert driver handle to loader handle
276-
%if item['optional']:
277-
if( nullptr != ${item['name']} )
278-
*${item['name']} = reinterpret_cast<${item['type']}>(
279-
context->${item['factory']}.getInstance( *${item['name']}, dditable ) );
280-
%else:
281-
%if re.match(r"\w+ImageCreate$", th.make_func_name(n, tags, obj)) or re.match(r"\w+SamplerCreate$", th.make_func_name(n, tags, obj)) or re.match(r"\w+ImageViewCreateExp$", th.make_func_name(n, tags, obj)):
282-
${item['type']} internalHandlePtr = *${item['name']};
283-
%endif
284-
*${item['name']} = reinterpret_cast<${item['type']}>(
285-
context->${item['factory']}.getInstance( *${item['name']}, dditable ) );
286-
%if re.match(r"\w+ImageCreate$", th.make_func_name(n, tags, obj)) or re.match(r"\w+ImageViewCreateExp$", th.make_func_name(n, tags, obj)):
287-
// convert loader handle to driver handle and store in map
288-
{
289-
std::lock_guard<std::mutex> lock(context->image_handle_map_lock);
290-
context->image_handle_map.insert({context->ze_image_factory.getInstance( internalHandlePtr, dditable ), internalHandlePtr});
291-
}
292-
%endif
293-
%if re.match(r"\w+SamplerCreate$", th.make_func_name(n, tags, obj)):
294-
// convert loader handle to driver handle and store in map
295-
{
296-
std::lock_guard<std::mutex> lock(context->sampler_handle_map_lock);
297-
context->sampler_handle_map.insert({context->ze_sampler_factory.getInstance( internalHandlePtr, dditable ), internalHandlePtr});
298-
}
299-
%endif
300-
%endif
301-
%endif
302-
}
303-
catch( std::bad_alloc& )
304-
{
305-
result = ${X}_RESULT_ERROR_OUT_OF_HOST_MEMORY;
306-
}
307-
%endif
308-
309-
%if 0 == i:
310-
%if re.match(r"\w+ModuleDynamicLink$", th.make_func_name(n, tags, obj)) or re.match(r"\w+ModuleCreate$", th.make_func_name(n, tags, obj)):
311-
if( ${X}_RESULT_SUCCESS != result )
312-
return result;
313-
314-
%endif
315-
%endif
316-
%endfor
317-
%endif
318215
return result;
319216
}
320217
%if 'condition' in obj:
321218
#endif // ${th.subt(n, tags, obj['condition'])}
322219
%endif
323220

221+
%endif
222+
%if re.match(r"Init", obj['name']) or re.match(r"\w+InitDrivers$", th.make_func_name(n, tags, obj)) or re.match(r"\w+DriverGet$", th.make_func_name(n, tags, obj)):
223+
return result;
224+
}
225+
%endif
324226
%endfor
227+
228+
///////////////////////////////////////////////////////////////////////////////
229+
/// @brief function for removing the ddi driver tables for ${n}
230+
__${x}dlllocal void ${X}_APICALL
231+
${n}DestroyDDiDriverTables(${n}_dditable_driver_t* pDdiTable)
232+
{
233+
// Delete ddi tables
234+
%for tbl in th.get_pfntables(specs, meta, n, tags):
235+
delete pDdiTable->${tbl['name']};
236+
%endfor
237+
delete pDdiTable;
238+
}
239+
325240
} // namespace loader
326241

327242
#if defined(__cplusplus)
@@ -419,6 +334,13 @@ ${tbl['export']['name']}(
419334
%endif
420335
{
421336
// return pointers to loader's DDIs
337+
%if namespace == "ze":
338+
loader::loaderDispatch->pCore->${tbl['name']} = new ${tbl['type']};
339+
%elif namespace == "zet":
340+
loader::loaderDispatch->pTools->${tbl['name']} = new ${tbl['type']};
341+
%elif namespace == "zes":
342+
loader::loaderDispatch->pSysman->${tbl['name']} = new ${tbl['type']};
343+
%endif
422344
%for obj in tbl['functions']:
423345
%if 'condition' in obj:
424346
#if ${th.subt(n, tags, obj['condition'])}
@@ -430,6 +352,7 @@ ${tbl['export']['name']}(
430352
#endif
431353
%endif
432354
%endfor
355+
${tbl['export']['name']}Legacy();
433356
}
434357
else
435358
{
@@ -477,4 +400,4 @@ ${tbl['export']['name']}(
477400

478401
#if defined(__cplusplus)
479402
};
480-
#endif
403+
#endif

scripts/templates/ldrddi.h.mako

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,19 @@ namespace loader
3232

3333
%endif
3434
%endfor
35+
__${x}dlllocal void ${X}_APICALL
36+
${n}DestroyDDiDriverTables(${n}_dditable_driver_t* pDdiTable);
3537
}
38+
39+
#if defined(__cplusplus)
40+
extern "C" {
41+
#endif
42+
43+
%for tbl in th.get_pfntables(specs, meta, n, tags):
44+
__${x}dlllocal void ${X}_APICALL
45+
${tbl['export']['name']}Legacy();
46+
%endfor
47+
48+
#if defined(__cplusplus)
49+
};
50+
#endif

0 commit comments

Comments
 (0)