@@ -22,6 +22,17 @@ from templates import helper as th
2222
2323namespace validation_layer
2424{
25+ % if n == ' ze' :
26+ // Forward declaration for Intel experimental extension
27+ // This is needed because zeDriverGetExtensionFunctionAddress needs to reference zexCounterBasedEventCreate2
28+ __zedlllocal ze_result_t ZE_APICALL zexCounterBasedEventCreate2(
29+ ze_context_handle_t hContext,
30+ ze_device_handle_t hDevice,
31+ const void *desc,
32+ ze_event_handle_t *phEvent
33+ );
34+
35+ %endif
2536 static ze_result_t logAndPropagateResult(const char* fname, ze_result_t result) {
2637 if (result != ${ X} _RESULT_SUCCESS) {
2738 context.logger->log_trace("Error (" + loader::to_string(result) + ") in " + std::string(fname));
@@ -78,6 +89,17 @@ ${line} \
7889 }
7990
8091 auto driver_result = ${ th.make_pfn_name(n, tags, obj)} ( ${ " , " .join(th.make_param_lines(n, tags, obj, format = [" name" ]))} );
92+ % if ' ppFunctionAddress' in [p.get(' name' , ' ' ) for p in obj.get(' params' , [])] and n == ' ze' :
93+
94+ // For Intel experimental extensions, we need to return our validation layer function
95+ // instead of the raw driver function so that validation/leak tracking works
96+ if (driver_result == ZE_RESULT_SUCCESS && ppFunctionAddress && name) {
97+ if (strcmp(name, "zexCounterBasedEventCreate2") == 0) {
98+ // Return our validation layer intercept function instead of the raw driver function
99+ *ppFunctionAddress = (void*)zexCounterBasedEventCreate2;
100+ }
101+ }
102+ %endif
81103
82104 for (size_t i = 0; i < numValHandlers; i++) {
83105 auto result = context.validationHandlers[i]->${ n} Validation->${ th.make_func_name(n, tags, obj)} Epilogue( \
@@ -127,6 +149,89 @@ ${line} \
127149 %endif
128150
129151 %endfor
152+ % if n == ' ze' :
153+ ///////////////////////////////////////////////////////////////////////////////
154+ /// @brief Intercept function for zexCounterBasedEventCreate2
155+ __zedlllocal ze_result_t ZE_APICALL zexCounterBasedEventCreate2(
156+ ze_context_handle_t hContext, ///< [in] handle of the context object
157+ ze_device_handle_t hDevice, ///< [in] handle of the device
158+ const void* desc, ///< [in] pointer to counter-based event descriptor
159+ ze_event_handle_t* phEvent ///< [out] pointer to handle of event object created
160+ )
161+ {
162+ context.logger->log_trace("zexCounterBasedEventCreate2(hContext, hDevice, desc, phEvent)");
163+
164+ // Note: This is an experimental function that may not have a DDI table entry.
165+ // For now, we'll return unsupported feature as this function should be
166+ // accessed through zeDriverGetExtensionFunctionAddress mechanism, but we
167+ // still want to track it in the validation layers for leak checking purposes.
168+
169+ auto numValHandlers = context.validationHandlers.size();
170+ for (size_t i = 0; i < numValHandlers; i++) {
171+ auto result = context.validationHandlers[i]->zeValidation->zexCounterBasedEventCreate2Prologue( hContext, hDevice, desc, phEvent );
172+ if(result!=ZE_RESULT_SUCCESS) return logAndPropagateResult("zexCounterBasedEventCreate2", result);
173+ }
174+
175+ if(context.enableThreadingValidation){
176+ //Unimplemented
177+ }
178+
179+ if(context.enableHandleLifetime){
180+ auto result = context.handleLifetime->zeHandleLifetime.zexCounterBasedEventCreate2Prologue( hContext, hDevice, desc, phEvent );
181+ if(result!=ZE_RESULT_SUCCESS) return logAndPropagateResult("zexCounterBasedEventCreate2", result);
182+ }
183+
184+ // This is an experimental function that must be accessed through the extension mechanism
185+ // We need to get the function pointer through zeDriverGetExtensionFunctionAddress
186+ ze_result_t driver_result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
187+
188+ // Get the real Intel experimental function through the extension mechanism
189+ auto pfnGetExtensionFunctionAddress = context.zeDdiTable.Driver.pfnGetExtensionFunctionAddress;
190+
191+ if (pfnGetExtensionFunctionAddress) {
192+ // Get the driver handle - use the first available driver
193+ ze_driver_handle_t hDriver = nullptr;
194+
195+ if (context.zeDdiTable.Driver.pfnGet) {
196+ uint32_t driverCount = 1;
197+ ze_driver_handle_t drivers[1] = {nullptr};
198+ auto result = context.zeDdiTable.Driver.pfnGet(&driverCount, drivers);
199+ if (result == ZE_RESULT_SUCCESS && driverCount > 0) {
200+ hDriver = drivers[0];
201+ }
202+ }
203+
204+ if (hDriver) {
205+ // Get the real Intel experimental function
206+ typedef ze_result_t (*zexCounterBasedEventCreate2_t)(ze_context_handle_t, ze_device_handle_t, const void*, ze_event_handle_t*);
207+ zexCounterBasedEventCreate2_t pfnRealFunction = nullptr;
208+
209+ auto ext_result = pfnGetExtensionFunctionAddress(hDriver, "zexCounterBasedEventCreate2", (void**)&pfnRealFunction);
210+
211+ if (ext_result == ZE_RESULT_SUCCESS && pfnRealFunction) {
212+ // Call the real Intel experimental function
213+ driver_result = pfnRealFunction(hContext, hDevice, desc, phEvent);
214+ } else {
215+ // Extension not available in this driver
216+ driver_result = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
217+ }
218+ }
219+ }
220+
221+ for (size_t i = 0; i < numValHandlers; i++) {
222+ auto result = context.validationHandlers[i]->zeValidation->zexCounterBasedEventCreate2Epilogue( hContext, hDevice, desc, phEvent, driver_result);
223+ if(result!=ZE_RESULT_SUCCESS) return logAndPropagateResult("zexCounterBasedEventCreate2", result);
224+ }
225+
226+ if(driver_result == ZE_RESULT_SUCCESS && context.enableHandleLifetime){
227+ if (phEvent){
228+ context.handleLifetime->addHandle( *phEvent );
229+ // Note: counter-based events may not have a traditional event pool dependency
230+ }
231+ }
232+ return logAndPropagateResult("zexCounterBasedEventCreate2", driver_result);
233+ }
234+ %endif
130235} // namespace validation_layer
131236
132237# if defined(__cplusplus)
0 commit comments