Skip to content

Commit 4e30108

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 19a9ce6 commit 4e30108

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
@@ -158,8 +158,28 @@ namespace loader
158158
{
159159
for( uint32_t i = 0; i < library_driver_handle_count; ++i ) {
160160
uint32_t driver_index = total_driver_handle_count + i;
161-
${obj['params'][1]['name']}[ driver_index ] = reinterpret_cast<${n}_driver_handle_t>(
162-
context->${n}_driver_factory.getInstance( ${obj['params'][1]['name']}[ driver_index ], &drv.dditable ) );
161+
if (drv.driverDDIHandleSupportQueried == false) {
162+
drv.properties = {};
163+
drv.properties.stype = ZE_STRUCTURE_TYPE_DRIVER_DDI_HANDLES_EXT_PROPERTIES;
164+
drv.properties.pNext = nullptr;
165+
ze_driver_properties_t driverProperties = {};
166+
driverProperties.stype = ZE_STRUCTURE_TYPE_DRIVER_PROPERTIES;
167+
driverProperties.pNext = nullptr;
168+
driverProperties.pNext = &drv.properties;
169+
ze_result_t res = drv.dditable.ze.Driver.pfnGetProperties(${obj['params'][1]['name']}[ driver_index ], &driverProperties);
170+
if (res != ZE_RESULT_SUCCESS) {
171+
if (loader::context->debugTraceEnabled) {
172+
std::string message = drv.name + " failed zeDriverGetProperties query, returned ";
173+
loader::context->debug_trace_message(message, loader::to_string(res));
174+
}
175+
return res;
176+
}
177+
drv.driverDDIHandleSupportQueried = true;
178+
}
179+
if (!(drv.properties.flags & ZE_DRIVER_DDI_HANDLE_EXT_FLAG_DDI_HANDLE_EXT_SUPPORTED)) {
180+
${obj['params'][1]['name']}[ driver_index ] = reinterpret_cast<${n}_driver_handle_t>(
181+
context->${n}_driver_factory.getInstance( ${obj['params'][1]['name']}[ driver_index ], &drv.dditable ) );
182+
}
163183
}
164184
}
165185
catch( std::bad_alloc& )
@@ -181,167 +201,62 @@ namespace loader
181201
%else:
182202
%for i, item in enumerate(th.get_loader_prologue(n, tags, obj, meta)):
183203
%if 0 == i:
184-
// extract driver's function pointer table
204+
// extract handle's function pointer table
185205
%if 'range' in item:
186-
auto dditable = reinterpret_cast<${item['obj']}*>( ${item['name']}[ 0 ] )->dditable;
187-
%else:
188-
auto dditable = reinterpret_cast<${item['obj']}*>( ${item['name']} )->dditable;
189-
%endif
190-
auto ${th.make_pfn_name(n, tags, obj)} = dditable->${n}.${th.get_table_name(n, tags, obj)}.${th.make_pfn_name(n, tags, obj)};
191-
if( nullptr == ${th.make_pfn_name(n, tags, obj)} )
192-
return ${X}_RESULT_ERROR_UNINITIALIZED;
193-
206+
%if namespace == "ze":
207+
auto dditable = reinterpret_cast<ze_handle_t*>( ${item['name']}[ 0 ] )->pCore;
208+
%elif namespace == "zet":
209+
auto dditable = reinterpret_cast<ze_handle_t*>( ${item['name']}[ 0 ] )->pTools;
210+
%elif namespace == "zes":
211+
auto dditable = reinterpret_cast<ze_handle_t*>( ${item['name']}[ 0 ] )->pSysman;
194212
%endif
195-
%if 'range' in item:
196-
<%
197-
add_local = True%>// convert loader handles to driver handles
198-
auto ${item['name']}Local = new ${item['type']} [${item['range'][1]}];
199-
<%
200-
arrays_to_delete.append(item['name']+ 'Local')
201-
%>for( size_t i = ${item['range'][0]}; ( nullptr != ${item['name']} ) && ( i < ${item['range'][1]} ); ++i )
202-
${item['name']}Local[ i ] = reinterpret_cast<${item['obj']}*>( ${item['name']}[ i ] )->handle;
203-
%else:
204-
%if item['optional']:
205-
// convert loader handle to driver handle
206-
${item['name']} = ( ${item['name']} ) ? reinterpret_cast<${item['obj']}*>( ${item['name']} )->handle : nullptr;
207213
%else:
208-
%if re.match(r"\w+ImageDestroy$", th.make_func_name(n, tags, obj)):
209-
// remove the handle from the kernel arugment map
210-
{
211-
std::lock_guard<std::mutex> lock(context->image_handle_map_lock);
212-
context->image_handle_map.erase(reinterpret_cast<ze_image_object_t*>(hImage));
213-
}
214-
%endif
215-
%if re.match(r"\w+SamplerDestroy$", th.make_func_name(n, tags, obj)):
216-
// remove the handle from the kernel arugment map
217-
{
218-
std::lock_guard<std::mutex> lock(context->sampler_handle_map_lock);
219-
context->sampler_handle_map.erase(reinterpret_cast<ze_sampler_object_t*>(hSampler));
220-
}
221-
%endif
222-
// convert loader handle to driver handle
223-
${item['name']} = reinterpret_cast<${item['obj']}*>( ${item['name']} )->handle;
214+
%if namespace == "ze":
215+
auto dditable = reinterpret_cast<ze_handle_t*>( ${item['name']} )->pCore;
216+
%elif namespace == "zet":
217+
auto dditable = reinterpret_cast<ze_handle_t*>( ${item['name']} )->pTools;
218+
%elif namespace == "zes":
219+
auto dditable = reinterpret_cast<ze_handle_t*>( ${item['name']} )->pSysman;
224220
%endif
225221
%endif
226-
227-
%endfor
228-
%if re.match(r"\w+KernelSetArgumentValue$", th.make_func_name(n, tags, obj)):
229-
// convert pArgValue to correct handle if applicable
230-
void *internalArgValue = const_cast<void *>(pArgValue);
231-
if (pArgValue) {
232-
// check if the arg value is a translated handle
233-
ze_image_object_t **imageHandle = static_cast<ze_image_object_t **>(internalArgValue);
234-
ze_sampler_object_t **samplerHandle = static_cast<ze_sampler_object_t **>(internalArgValue);
235-
{
236-
std::lock_guard<std::mutex> image_lock(context->image_handle_map_lock);
237-
std::lock_guard<std::mutex> sampler_lock(context->sampler_handle_map_lock);
238-
if( context->image_handle_map.find(*imageHandle) != context->image_handle_map.end() ) {
239-
internalArgValue = &context->image_handle_map[*imageHandle];
240-
} else if( context->sampler_handle_map.find(*samplerHandle) != context->sampler_handle_map.end() ) {
241-
internalArgValue = &context->sampler_handle_map[*samplerHandle];
242-
}
243-
}
222+
if (dditable->isValidFlag == 0)
223+
return ${X}_RESULT_ERROR_UNINITIALIZED;
224+
// Check that api version in the driver is supported by this version of the API
225+
if (dditable->version < ${th.get_version(obj)}) {
226+
return ${X}_RESULT_ERROR_UNSUPPORTED_VERSION;
244227
}
228+
auto ${th.make_pfn_name(n, tags, obj)} = dditable->${th.get_table_name(n, tags, obj)}->${th.make_pfn_name(n, tags, obj)};
229+
if( nullptr == ${th.make_pfn_name(n, tags, obj)} )
230+
return ${X}_RESULT_ERROR_UNINITIALIZED;
245231
%endif
246-
## Workaround due to incorrect defintion of phWaitEvents in the ze headers which missed the range values.
247-
## To be removed once the headers have been updated in a new spec release.
248-
%if re.match(r"\w+CommandListAppendMetricQueryEnd$", th.make_func_name(n, tags, obj)):
249-
// convert loader handles to driver handles
250-
auto phWaitEventsLocal = new ze_event_handle_t [numWaitEvents];
251-
for( size_t i = 0; ( nullptr != phWaitEvents ) && ( i < numWaitEvents ); ++i )
252-
phWaitEventsLocal[ i ] = reinterpret_cast<ze_event_object_t*>( phWaitEvents[ i ] )->handle;
253-
254-
// forward to device-driver
255-
result = pfnAppendMetricQueryEnd( hCommandList, hMetricQuery, hSignalEvent, numWaitEvents, phWaitEventsLocal );
256-
delete []phWaitEventsLocal;
257-
%else:
258-
// forward to device-driver
259-
%if add_local:
260-
result = ${th.make_pfn_name(n, tags, obj)}( ${", ".join(th.make_param_lines(n, tags, obj, format=["name", "local"]))} );
261-
%for array_name in arrays_to_delete:
262-
delete []${array_name};
263232
%endfor
264-
%else:
265-
%if re.match(r"\w+KernelSetArgumentValue$", th.make_func_name(n, tags, obj)):
266-
result = pfnSetArgumentValue( hKernel, argIndex, argSize, const_cast<const void *>(internalArgValue) );
267-
%else:
233+
// forward to device-driver
268234
result = ${th.make_pfn_name(n, tags, obj)}( ${", ".join(th.make_param_lines(n, tags, obj, format=["name"]))} );
269-
%endif
270-
%endif
271-
%endif
272-
<%
273-
del arrays_to_delete
274-
del add_local%>
275-
%for i, item in enumerate(th.get_loader_epilogue(n, tags, obj, meta)):
276-
%if 0 == i:
277-
%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)):
278-
if( ${X}_RESULT_SUCCESS != result )
279-
return result;
280-
281-
%endif
282-
%endif
283-
%if item['release']:
284-
// release loader handle
285-
context->${item['factory']}.release( ${item['name']} );
286-
%else:
287-
try
288-
{
289-
%if 'range' in item:
290-
// convert driver handles to loader handles
291-
for( size_t i = ${item['range'][0]}; ( nullptr != ${item['name']} ) && ( i < ${item['range'][1]} ); ++i )
292-
${item['name']}[ i ] = reinterpret_cast<${item['type']}>(
293-
context->${item['factory']}.getInstance( ${item['name']}[ i ], dditable ) );
294-
%else:
295-
// convert driver handle to loader handle
296-
%if item['optional']:
297-
if( nullptr != ${item['name']} )
298-
*${item['name']} = reinterpret_cast<${item['type']}>(
299-
context->${item['factory']}.getInstance( *${item['name']}, dditable ) );
300-
%else:
301-
%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)):
302-
${item['type']} internalHandlePtr = *${item['name']};
303-
%endif
304-
*${item['name']} = reinterpret_cast<${item['type']}>(
305-
context->${item['factory']}.getInstance( *${item['name']}, dditable ) );
306-
%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)):
307-
// convert loader handle to driver handle and store in map
308-
{
309-
std::lock_guard<std::mutex> lock(context->image_handle_map_lock);
310-
context->image_handle_map.insert({context->ze_image_factory.getInstance( internalHandlePtr, dditable ), internalHandlePtr});
311-
}
312-
%endif
313-
%if re.match(r"\w+SamplerCreate$", th.make_func_name(n, tags, obj)):
314-
// convert loader handle to driver handle and store in map
315-
{
316-
std::lock_guard<std::mutex> lock(context->sampler_handle_map_lock);
317-
context->sampler_handle_map.insert({context->ze_sampler_factory.getInstance( internalHandlePtr, dditable ), internalHandlePtr});
318-
}
319-
%endif
320-
%endif
321-
%endif
322-
}
323-
catch( std::bad_alloc& )
324-
{
325-
result = ${X}_RESULT_ERROR_OUT_OF_HOST_MEMORY;
326-
}
327-
%endif
328-
329-
%if 0 == i:
330-
%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)):
331-
if( ${X}_RESULT_SUCCESS != result )
332-
return result;
333-
334-
%endif
335-
%endif
336-
%endfor
337-
%endif
338235
return result;
339236
}
340237
%if 'condition' in obj:
341238
#endif // ${th.subt(n, tags, obj['condition'])}
342239
%endif
343240

241+
%endif
242+
%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)):
243+
return result;
244+
}
245+
%endif
344246
%endfor
247+
248+
///////////////////////////////////////////////////////////////////////////////
249+
/// @brief function for removing the ddi driver tables for ${n}
250+
__${x}dlllocal void ${X}_APICALL
251+
${n}DestroyDDiDriverTables(${n}_dditable_driver_t* pDdiTable)
252+
{
253+
// Delete ddi tables
254+
%for tbl in th.get_pfntables(specs, meta, n, tags):
255+
delete pDdiTable->${tbl['name']};
256+
%endfor
257+
delete pDdiTable;
258+
}
259+
345260
} // namespace loader
346261

347262
#if defined(__cplusplus)
@@ -439,6 +354,13 @@ ${tbl['export']['name']}(
439354
%endif
440355
{
441356
// return pointers to loader's DDIs
357+
%if namespace == "ze":
358+
loader::loaderDispatch->pCore->${tbl['name']} = new ${tbl['type']};
359+
%elif namespace == "zet":
360+
loader::loaderDispatch->pTools->${tbl['name']} = new ${tbl['type']};
361+
%elif namespace == "zes":
362+
loader::loaderDispatch->pSysman->${tbl['name']} = new ${tbl['type']};
363+
%endif
442364
%for obj in tbl['functions']:
443365
%if 'condition' in obj:
444366
#if ${th.subt(n, tags, obj['condition'])}
@@ -450,6 +372,7 @@ ${tbl['export']['name']}(
450372
#endif
451373
%endif
452374
%endfor
375+
${tbl['export']['name']}Legacy();
453376
}
454377
else
455378
{
@@ -497,4 +420,4 @@ ${tbl['export']['name']}(
497420

498421
#if defined(__cplusplus)
499422
};
500-
#endif
423+
#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)