// test_chaining_v2.m — Deep exploration of _ANEChainingRequest and related APIs // Phases: // 1. Dump unexplored ANE classes (mapper, buffer, output sets, etc.) // 2. Query compiled model for symbol names and I/O mapping // 3. Try _ANEProgramIOSurfacesMapper and _ANEBuffer for indexed IOSurfaces // 4. Retry ChainingRequest with indexed surfaces // 5. Test real-time eval path and perfStatsMask // 6. Print structured summary #import #import #import #import #import #import #include static mach_timebase_info_data_t g_tb; static double tb_ms(uint64_t t) { return (double)t * g_tb.numer / g_tb.denom / 1e6; } static int g_fp16_io = 0; #pragma mark — Helpers static void dump_class(const char *name) { Class cls = NSClassFromString([NSString stringWithUTF8String:name]); if (!cls) { printf(" %s: NOT FOUND\n", name); return; } printf("\n=== %s ===\n", name); unsigned int count; Method *methods = class_copyMethodList(object_getClass(cls), &count); if (count) printf(" Class methods (%u):\n", count); for (unsigned int i = 0; i < count; i++) { SEL s = method_getName(methods[i]); const char *enc = method_getTypeEncoding(methods[i]); printf(" + %s [%s]\n", sel_getName(s), enc ? enc : "?"); } free(methods); methods = class_copyMethodList(cls, &count); if (count) printf(" Instance methods (%u):\n", count); for (unsigned int i = 0; i < count; i++) { SEL s = method_getName(methods[i]); const char *enc = method_getTypeEncoding(methods[i]); printf(" - %s [%s]\n", sel_getName(s), enc ? enc : "?"); } free(methods); unsigned int pcount; objc_property_t *props = class_copyPropertyList(cls, &pcount); if (pcount) printf(" Properties (%u):\n", pcount); for (unsigned int i = 0; i < pcount; i++) { const char *pname = property_getName(props[i]); const char *pattr = property_getAttributes(props[i]); printf(" @property %s [%s]\n", pname, pattr ? pattr : "?"); } free(props); } static void try_alloc_init(const char *name) { Class cls = NSClassFromString([NSString stringWithUTF8String:name]); if (!cls) return; @try { id obj = [[cls alloc] init]; printf(" %s alloc/init: %s\n", name, obj ? [[obj description] UTF8String] : "nil"); } @catch (NSException *ex) { printf(" %s alloc/init EXCEPTION: %s\n", name, [[ex reason] UTF8String]); } } static void dump_all_properties(id obj, Class cls) { if (!obj) return; unsigned int pcount; objc_property_t *props = class_copyPropertyList(cls, &pcount); for (unsigned int i = 0; i < pcount; i++) { const char *pname = property_getName(props[i]); @try { id val = [obj valueForKey:[NSString stringWithUTF8String:pname]]; printf(" %s = %s\n", pname, val ? [[val description] UTF8String] : "nil"); } @catch (NSException *ex) { printf(" %s = \n", pname, [[ex reason] UTF8String]); } } free(props); } static IOSurfaceRef make_surface(size_t bytes) { return IOSurfaceCreate((__bridge CFDictionaryRef)@{ (id)kIOSurfaceWidth:@(bytes), (id)kIOSurfaceHeight:@1, (id)kIOSurfaceBytesPerElement:@1, (id)kIOSurfaceBytesPerRow:@(bytes), (id)kIOSurfaceAllocSize:@(bytes), (id)kIOSurfacePixelFormat:@0}); } typedef struct { id model; IOSurfaceRef ioIn, ioOut; NSString *tmpDir; } CompiledKernel; static NSString *gen_conv_mil(int ch, int sp) { if (g_fp16_io) { return [NSString stringWithFormat: @"program(1.0)\n[buildInfo = dict, tensor>({{\"coremlc-version\", \"3505.4.1\"}})]\n{\n" " func main(tensor x) {\n" " tensor pt = const()[name=tensor(\"pt\"), val=tensor(\"valid\")];\n" " tensor st = const()[name=tensor(\"st\"), val=tensor([1,1])];\n" " tensor pd = const()[name=tensor(\"pd\"), val=tensor([0,0,0,0])];\n" " tensor dl = const()[name=tensor(\"dl\"), val=tensor([1,1])];\n" " tensor gr = const()[name=tensor(\"gr\"), val=tensor(1)];\n" " tensor W = const()[name=tensor(\"W\"), " "val=tensor(BLOBFILE(path=tensor(\"@model_path/weights/weight.bin\"), offset=tensor(64)))];\n" " tensor y = conv(dilations=dl,groups=gr,pad=pd,pad_type=pt,strides=st,weight=W,x=x)" "[name=tensor(\"conv\")];\n" " } -> (y);\n}\n", ch, sp, ch, ch, ch, ch, ch, sp]; } return [NSString stringWithFormat: @"program(1.0)\n[buildInfo = dict, tensor>({{\"coremlc-version\", \"3505.4.1\"}})]\n{\n" " func main(tensor x) {\n" " tensor pt = const()[name=tensor(\"pt\"), val=tensor(\"valid\")];\n" " tensor st = const()[name=tensor(\"st\"), val=tensor([1,1])];\n" " tensor pd = const()[name=tensor(\"pd\"), val=tensor([0,0,0,0])];\n" " tensor dl = const()[name=tensor(\"dl\"), val=tensor([1,1])];\n" " tensor gr = const()[name=tensor(\"gr\"), val=tensor(1)];\n" " tensor to16 = const()[name=tensor(\"to16\"), val=tensor(\"fp16\")];\n" " tensor x16 = cast(dtype=to16,x=x)[name=tensor(\"cin\")];\n" " tensor W = const()[name=tensor(\"W\"), " "val=tensor(BLOBFILE(path=tensor(\"@model_path/weights/weight.bin\"), offset=tensor(64)))];\n" " tensor y16 = conv(dilations=dl,groups=gr,pad=pd,pad_type=pt,strides=st,weight=W,x=x16)" "[name=tensor(\"conv\")];\n" " tensor to32 = const()[name=tensor(\"to32\"), val=tensor(\"fp32\")];\n" " tensor y = cast(dtype=to32,x=y16)[name=tensor(\"cout\")];\n" " } -> (y);\n}\n", ch, sp, ch, sp, ch, ch, ch, ch, ch, sp, ch, sp]; } static CompiledKernel compile_kernel(Class gD, Class gI, int ch, int sp, NSData *wdata) { CompiledKernel k = {0}; NSFileManager *fm = [NSFileManager defaultManager]; NSString *mil = gen_conv_mil(ch, sp); NSData *md = [mil dataUsingEncoding:NSUTF8StringEncoding]; id desc = ((id(*)(Class,SEL,id,id,id))objc_msgSend)(gD, @selector(modelWithMILText:weights:optionsPlist:), md, @{@"@model_path/weights/weight.bin": @{@"offset":@0, @"data":wdata}}, nil); id mdl = ((id(*)(Class,SEL,id))objc_msgSend)(gI, @selector(inMemoryModelWithDescriptor:), desc); id hx = ((id(*)(id,SEL))objc_msgSend)(mdl, @selector(hexStringIdentifier)); NSString *td = [NSTemporaryDirectory() stringByAppendingPathComponent:hx]; [fm createDirectoryAtPath:[td stringByAppendingPathComponent:@"weights"] withIntermediateDirectories:YES attributes:nil error:nil]; [md writeToFile:[td stringByAppendingPathComponent:@"model.mil"] atomically:YES]; [wdata writeToFile:[td stringByAppendingPathComponent:@"weights/weight.bin"] atomically:YES]; NSError *e = nil; BOOL ok = ((BOOL(*)(id,SEL,unsigned int,id,NSError**))objc_msgSend)( mdl, @selector(compileWithQoS:options:error:), 21, @{}, &e); if (!ok) { if (!g_fp16_io) { printf(" fp32 compile failed, retrying with fp16 I/O\n"); g_fp16_io = 1; [fm removeItemAtPath:td error:nil]; return compile_kernel(gD, gI, ch, sp, wdata); } printf(" Compile failed: %s\n", e ? [[e description] UTF8String] : "unknown"); return k; } ((BOOL(*)(id,SEL,unsigned int,id,NSError**))objc_msgSend)( mdl, @selector(loadWithQoS:options:error:), 21, @{}, &e); int bpe = g_fp16_io ? 2 : 4; k.model = mdl; k.ioIn = make_surface(ch * sp * bpe); k.ioOut = make_surface(ch * sp * bpe); k.tmpDir = td; return k; } #pragma mark — Result tracking typedef struct { bool phase1_done; int classes_found; int classes_missing; bool phase2_done; bool has_input_symbols; bool has_output_symbols; bool has_program_handle; bool phase3_done; bool mapper_works; bool buffer_works; bool got_symbol_index; bool phase4_done; bool validate_passed; bool chaining_executed; double sequential_ms; double chained_ms; bool phase5_done; bool realtime_eval_works; bool perfstats_works; uint64_t hw_exec_time_ns; bool phase7_done; bool outputsets_with_stats_works; bool chaining_with_stats_works; bool phase8_done; bool disk_model_loads; bool disk_model_has_symbols; bool phase9_done; bool process_request_works; double process_request_ms; bool phase10_done; bool shared_events_exist; double rt_eval_ms; double std_eval_ms; double direct_eval_ms; } Results; int main() { @autoreleasepool { setbuf(stdout, NULL); mach_timebase_info(&g_tb); dlopen("/System/Library/PrivateFrameworks/AppleNeuralEngine.framework/AppleNeuralEngine", RTLD_NOW); Results R = {0}; printf("╔══════════════════════════════════════════════════════════╗\n"); printf("║ ANE ChainingRequest Deep Exploration v2 ║\n"); printf("╚══════════════════════════════════════════════════════════╝\n\n"); Class gD = NSClassFromString(@"_ANEInMemoryModelDescriptor"); Class gI = NSClassFromString(@"_ANEInMemoryModel"); Class gAR = NSClassFromString(@"_ANERequest"); Class gAIO = NSClassFromString(@"_ANEIOSurfaceObject"); Class gClient= NSClassFromString(@"_ANEClient"); Class gChain = NSClassFromString(@"_ANEChainingRequest"); if (!gD || !gI || !gAR || !gAIO) { printf("FATAL: Core ANE classes not found\n"); return 1; } // ===================================================================== // PHASE 1: Dump all unexplored ANE classes // ===================================================================== printf("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); printf(" PHASE 1: Class Introspection (unexplored classes)\n"); printf("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); const char *explore_classes[] = { "_ANEProgramIOSurfacesMapper", "_ANEBuffer", "_ANEProgramForEvaluation", "_ANEIOSurfaceOutputSets", "_ANEInputBuffersReady", "_ANEOutputSetEnqueue", "_ANEModelInstanceParameters", "_ANEDeviceController", "_ANEQoSMapper", NULL }; for (int i = 0; explore_classes[i]; i++) { Class cls = NSClassFromString([NSString stringWithUTF8String:explore_classes[i]]); if (cls) R.classes_found++; else R.classes_missing++; dump_class(explore_classes[i]); } printf("\n --- Alloc/init tests ---\n"); for (int i = 0; explore_classes[i]; i++) { try_alloc_init(explore_classes[i]); } printf("\n --- Also dump _ANEIOSurfaceObject (for symbolIndex) ---\n"); dump_class("_ANEIOSurfaceObject"); dump_class("_ANEChainingRequest"); dump_class("_ANEClient"); R.phase1_done = true; printf("\n Phase 1 complete: %d classes found, %d missing\n", R.classes_found, R.classes_missing); // ===================================================================== // Compile test kernel (shared by subsequent phases) // ===================================================================== printf("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); printf(" Compiling test kernels...\n"); printf("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); int CH = 64, SP = 32; _Float16 *w = (_Float16*)calloc(CH*CH, sizeof(_Float16)); for (int i = 0; i < CH; i++) w[i*CH+i] = (_Float16)0.5f; int ws = CH*CH*2, tot = 128+ws; uint8_t *blob = (uint8_t*)calloc(tot, 1); blob[0]=1; blob[4]=2; blob[64]=0xEF; blob[65]=0xBE; blob[66]=0xAD; blob[67]=0xDE; blob[68]=1; *(uint32_t*)(blob+72)=ws; *(uint32_t*)(blob+80)=128; memcpy(blob+128, w, ws); NSData *wdata = [NSData dataWithBytesNoCopy:blob length:tot freeWhenDone:YES]; free(w); CompiledKernel k1 = compile_kernel(gD, gI, CH, SP, wdata); CompiledKernel k2 = compile_kernel(gD, gI, CH, SP, wdata); if (!k1.model || !k2.model) { printf("FATAL: Failed to compile test kernels\n"); return 1; } printf(" Kernel 1: compiled and loaded (fp16_io=%d)\n", g_fp16_io); printf(" Kernel 2: compiled and loaded\n"); int bpe = g_fp16_io ? 2 : 4; int ioBytes = CH * SP * bpe; IOSurfaceLock(k1.ioIn, 0, NULL); if (g_fp16_io) { _Float16 *inp = (_Float16*)IOSurfaceGetBaseAddress(k1.ioIn); for (int i = 0; i < CH*SP; i++) inp[i] = (_Float16)1.0f; } else { float *inp = (float*)IOSurfaceGetBaseAddress(k1.ioIn); for (int i = 0; i < CH*SP; i++) inp[i] = 1.0f; } IOSurfaceUnlock(k1.ioIn, 0, NULL); // ===================================================================== // PHASE 2: Symbol Name Discovery // ===================================================================== printf("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); printf(" PHASE 2: Symbol Name Discovery\n"); printf("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); const char *model_keys[] = { "inputSymbolNames", "outputSymbolNames", "programHandle", "intermediateBufferHandle", "hexStringIdentifier", "modelDescription", "inputFeatureNames", "outputFeatureNames", "perfStatsMask", "numberOfInputs", "numberOfOutputs", "compiledModelPath", "compiledModelURL", "modelPath", "modelURL", NULL }; printf("\n --- _ANEInMemoryModel properties (k1) ---\n"); for (int i = 0; model_keys[i]; i++) { NSString *key = [NSString stringWithUTF8String:model_keys[i]]; @try { id val = [k1.model valueForKey:key]; const char *desc = val ? [[val description] UTF8String] : "nil"; size_t len = strlen(desc); if (len > 200) { printf(" %s = %.200s... (truncated, %zu chars)\n", model_keys[i], desc, len); } else { printf(" %s = %s\n", model_keys[i], desc); } if (strcmp(model_keys[i], "inputSymbolNames") == 0 && val) R.has_input_symbols = true; if (strcmp(model_keys[i], "outputSymbolNames") == 0 && val) R.has_output_symbols = true; if (strcmp(model_keys[i], "programHandle") == 0 && val) R.has_program_handle = true; } @catch (NSException *ex) { printf(" %s = \n", model_keys[i], [[ex reason] UTF8String]); } } printf("\n --- Full property dump of _ANEInMemoryModel ---\n"); { unsigned int pcount; objc_property_t *props = class_copyPropertyList(gI, &pcount); printf(" (%u properties declared on class)\n", pcount); for (unsigned int i = 0; i < pcount; i++) { const char *pname = property_getName(props[i]); const char *pattr = property_getAttributes(props[i]); printf(" @property %s [%s]\n", pname, pattr ? pattr : "?"); @try { id val = [k1.model valueForKey:[NSString stringWithUTF8String:pname]]; const char *desc = val ? [[val description] UTF8String] : "nil"; size_t len = strlen(desc); if (len > 200) { printf(" value = %.200s... (truncated)\n", desc); } else { printf(" value = %s\n", desc); } } @catch (NSException *ex) { printf(" value = \n", [[ex reason] UTF8String]); } } free(props); } printf("\n --- Walk superclasses for inherited properties ---\n"); { Class c = gI; while (c) { const char *cname = class_getName(c); if (strstr(cname, "ANE")) { unsigned int pcount; objc_property_t *props = class_copyPropertyList(c, &pcount); if (pcount > 0) { printf(" %s (%u props):\n", cname, pcount); for (unsigned int i = 0; i < pcount; i++) { const char *pname = property_getName(props[i]); printf(" @property %s\n", pname); } } free(props); } c = class_getSuperclass(c); } } printf("\n --- _ANEIOSurfaceObject introspection ---\n"); { id wI = ((id(*)(Class,SEL,IOSurfaceRef))objc_msgSend)(gAIO, @selector(objectWithIOSurface:), k1.ioIn); printf(" wI description: %s\n", [[wI description] UTF8String]); unsigned int pcount; objc_property_t *props = class_copyPropertyList(gAIO, &pcount); for (unsigned int i = 0; i < pcount; i++) { const char *pname = property_getName(props[i]); @try { id val = [wI valueForKey:[NSString stringWithUTF8String:pname]]; printf(" %s = %s\n", pname, val ? [[val description] UTF8String] : "nil"); } @catch (NSException *ex) { printf(" %s = \n", pname, [[ex reason] UTF8String]); } } free(props); @try { id symIdx = [wI valueForKey:@"symbolIndex"]; printf(" symbolIndex (KVC): %s\n", symIdx ? [[symIdx description] UTF8String] : "nil"); } @catch (NSException *ex) { printf(" symbolIndex (KVC): \n", [[ex reason] UTF8String]); } } R.phase2_done = true; printf("\n Phase 2 complete: inputSymbols=%s outputSymbols=%s programHandle=%s\n", R.has_input_symbols ? "YES" : "NO", R.has_output_symbols ? "YES" : "NO", R.has_program_handle ? "YES" : "NO"); // Create IOSurface wrapper objects (shared across Phases 3-5) id wI1 = ((id(*)(Class,SEL,IOSurfaceRef))objc_msgSend)(gAIO, @selector(objectWithIOSurface:), k1.ioIn); id wO1 = ((id(*)(Class,SEL,IOSurfaceRef))objc_msgSend)(gAIO, @selector(objectWithIOSurface:), k1.ioOut); id wI2 = ((id(*)(Class,SEL,IOSurfaceRef))objc_msgSend)(gAIO, @selector(objectWithIOSurface:), k2.ioIn); id wO2 = ((id(*)(Class,SEL,IOSurfaceRef))objc_msgSend)(gAIO, @selector(objectWithIOSurface:), k2.ioOut); id req1 = ((id(*)(Class,SEL,id,id,id,id,id,id,id))objc_msgSend)(gAR, @selector(requestWithInputs:inputIndices:outputs:outputIndices:weightsBuffer:perfStats:procedureIndex:), @[wI1], @[@0], @[wO1], @[@0], nil, nil, @0); id req2 = ((id(*)(Class,SEL,id,id,id,id,id,id,id))objc_msgSend)(gAR, @selector(requestWithInputs:inputIndices:outputs:outputIndices:weightsBuffer:perfStats:procedureIndex:), @[wI2], @[@0], @[wO2], @[@0], nil, nil, @0); NSError *e = nil; // ===================================================================== // PHASE 3: IOSurface Mapper & _ANEBuffer // ===================================================================== printf("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); printf(" PHASE 3: IOSurface Mapper & Buffer Experiments\n"); printf("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); uint64_t progHandle = 0; @try { id ph = [k1.model valueForKey:@"programHandle"]; if (ph) progHandle = [ph unsignedLongLongValue]; } @catch (NSException *ex) { (void)ex; } printf(" k1 programHandle = %llu\n", progHandle); // 3a: Try _ANEProgramIOSurfacesMapper // API: +mapperWithController:(id)ctrl | +mapperWithProgramHandle:(uint64_t)handle Class gMapper = NSClassFromString(@"_ANEProgramIOSurfacesMapper"); if (gMapper) { printf("\n --- 3a: _ANEProgramIOSurfacesMapper ---\n"); // Try mapperWithProgramHandle: (takes uint64_t) id mapper = nil; if (progHandle) { @try { mapper = ((id(*)(Class,SEL,uint64_t))objc_msgSend)(gMapper, @selector(mapperWithProgramHandle:), progHandle); printf(" mapperWithProgramHandle(%llu): %s\n", progHandle, mapper ? [[mapper description] UTF8String] : "nil"); if (mapper) { R.mapper_works = true; dump_all_properties(mapper, gMapper); } } @catch (NSException *ex) { printf(" mapperWithProgramHandle EXCEPTION: %s\n", [[ex reason] UTF8String]); } } // Try mapperWithController: using model's sharedConnection or DeviceController if (!mapper) { @try { id devCtrl = nil; Class gDevCtrl = NSClassFromString(@"_ANEDeviceController"); if (gDevCtrl) { devCtrl = ((id(*)(Class,SEL,uint64_t))objc_msgSend)(gDevCtrl, @selector(controllerWithProgramHandle:), progHandle); printf(" _ANEDeviceController.controllerWithProgramHandle: %s\n", devCtrl ? [[devCtrl description] UTF8String] : "nil"); } if (devCtrl) { mapper = ((id(*)(Class,SEL,id))objc_msgSend)(gMapper, @selector(mapperWithController:), devCtrl); printf(" mapperWithController: %s\n", mapper ? [[mapper description] UTF8String] : "nil"); if (mapper) { R.mapper_works = true; dump_all_properties(mapper, gMapper); } } } @catch (NSException *ex) { printf(" mapperWithController EXCEPTION: %s\n", [[ex reason] UTF8String]); } } // Try mapIOSurfacesWithModel:request:cacheInference:error: if we have a mapper if (mapper) { printf("\n Trying mapIOSurfacesWithModel...\n"); id reqMap = ((id(*)(Class,SEL,id,id,id,id,id,id,id))objc_msgSend)(gAR, @selector(requestWithInputs:inputIndices:outputs:outputIndices:weightsBuffer:perfStats:procedureIndex:), @[wI1], @[@0], @[wO1], @[@0], nil, nil, @0); @try { NSError *mapErr = nil; BOOL mapOk = ((BOOL(*)(id,SEL,id,id,BOOL,NSError**))objc_msgSend)( mapper, @selector(mapIOSurfacesWithModel:request:cacheInference:error:), k1.model, reqMap, NO, &mapErr); printf(" mapIOSurfacesWithModel: %s\n", mapOk ? "YES" : "NO"); if (!mapOk && mapErr) printf(" error: %s\n", [[mapErr description] UTF8String]); } @catch (NSException *ex) { printf(" mapIOSurfacesWithModel EXCEPTION: %s\n", [[ex reason] UTF8String]); } // Also try validateRequest:model: @try { BOOL validReq = ((BOOL(*)(id,SEL,id,id))objc_msgSend)( mapper, @selector(validateRequest:model:), reqMap, k1.model); printf(" validateRequest:model: %s\n", validReq ? "YES" : "NO"); } @catch (NSException *ex) { printf(" validateRequest:model: EXCEPTION: %s\n", [[ex reason] UTF8String]); } } } else { printf("\n _ANEProgramIOSurfacesMapper: NOT FOUND\n"); } // 3b: Try _ANEBuffer // API: +bufferWithIOSurfaceObject:(id)ioSurfObj symbolIndex:(id)symIdx source:(long long)src Class gBuffer = NSClassFromString(@"_ANEBuffer"); if (gBuffer) { printf("\n --- 3b: _ANEBuffer ---\n"); id wBufTest = ((id(*)(Class,SEL,IOSurfaceRef))objc_msgSend)(gAIO, @selector(objectWithIOSurface:), k1.ioIn); for (long long src = 0; src <= 2; src++) { @try { id buf = ((id(*)(Class,SEL,id,id,long long))objc_msgSend)(gBuffer, @selector(bufferWithIOSurfaceObject:symbolIndex:source:), wBufTest, @0, src); printf(" bufferWithIOSurfaceObject(symIdx=0, source=%lld): %s\n", src, buf ? [[buf description] UTF8String] : "nil"); if (buf) { R.buffer_works = true; dump_all_properties(buf, gBuffer); @try { id symIdx = [buf valueForKey:@"symbolIndex"]; printf(" symbolIndex = %s\n", symIdx ? [[symIdx description] UTF8String] : "nil"); if (symIdx) R.got_symbol_index = true; } @catch (NSException *ex) { printf(" symbolIndex: \n"); } } } @catch (NSException *ex) { printf(" bufferWithIOSurfaceObject(source=%lld) EXCEPTION: %s\n", src, [[ex reason] UTF8String]); } } @try { id buf1 = ((id(*)(Class,SEL,id,id,long long))objc_msgSend)(gBuffer, @selector(bufferWithIOSurfaceObject:symbolIndex:source:), wBufTest, @1, (long long)0); printf(" bufferWithIOSurfaceObject(symIdx=1, source=0): %s\n", buf1 ? [[buf1 description] UTF8String] : "nil"); if (buf1) { R.buffer_works = true; dump_all_properties(buf1, gBuffer); } } @catch (NSException *ex) { printf(" bufferWithIOSurfaceObject(symIdx=1) EXCEPTION: %s\n", [[ex reason] UTF8String]); } } else { printf("\n _ANEBuffer: NOT FOUND\n"); } // 3c: Try _ANEIOSurfaceObject with symbolIndex setter printf("\n --- 3c: _ANEIOSurfaceObject symbolIndex experiment ---\n"); { id wTest = ((id(*)(Class,SEL,IOSurfaceRef))objc_msgSend)(gAIO, @selector(objectWithIOSurface:), k1.ioIn); if ([wTest respondsToSelector:@selector(setSymbolIndex:)]) { printf(" setSymbolIndex: is available!\n"); @try { ((void(*)(id,SEL,NSUInteger))objc_msgSend)(wTest, @selector(setSymbolIndex:), 0); printf(" setSymbolIndex:0 succeeded\n"); R.got_symbol_index = true; } @catch (NSException *ex) { printf(" setSymbolIndex:0 EXCEPTION: %s\n", [[ex reason] UTF8String]); } } else { printf(" setSymbolIndex: NOT available on _ANEIOSurfaceObject\n"); } if ([wTest respondsToSelector:NSSelectorFromString(@"symbolIndex")]) { printf(" symbolIndex getter: available\n"); @try { NSUInteger idx = ((NSUInteger(*)(id,SEL))objc_msgSend)(wTest, NSSelectorFromString(@"symbolIndex")); printf(" symbolIndex = %lu\n", (unsigned long)idx); } @catch (NSException *ex) { printf(" symbolIndex getter EXCEPTION: %s\n", [[ex reason] UTF8String]); } } else { printf(" symbolIndex getter: NOT available\n"); } SEL selObjWithSurfaceIdx = NSSelectorFromString(@"objectWithIOSurface:symbolIndex:"); if ([gAIO respondsToSelector:selObjWithSurfaceIdx]) { printf(" +objectWithIOSurface:symbolIndex: is available!\n"); @try { id wIndexed = ((id(*)(Class,SEL,IOSurfaceRef,NSUInteger))objc_msgSend)( gAIO, selObjWithSurfaceIdx, k1.ioIn, (NSUInteger)0); printf(" result: %s\n", wIndexed ? [[wIndexed description] UTF8String] : "nil"); if (wIndexed) R.got_symbol_index = true; } @catch (NSException *ex) { printf(" EXCEPTION: %s\n", [[ex reason] UTF8String]); } } else { printf(" +objectWithIOSurface:symbolIndex: NOT available\n"); } } // 3d: Try setting symbolIndex on IOSurface itself (as IOSurface property) printf("\n --- 3d: IOSurface property experiments ---\n"); { IOSurfaceLock(k1.ioIn, 0, NULL); IOSurfaceSetValue(k1.ioIn, CFSTR("symbolIndex"), (__bridge CFTypeRef)@0); IOSurfaceUnlock(k1.ioIn, 0, NULL); CFTypeRef val = IOSurfaceCopyValue(k1.ioIn, CFSTR("symbolIndex")); printf(" IOSurface 'symbolIndex' property: %s\n", val ? [(__bridge id)val description].UTF8String : "nil"); if (val) CFRelease(val); id wWithProp = ((id(*)(Class,SEL,IOSurfaceRef))objc_msgSend)(gAIO, @selector(objectWithIOSurface:), k1.ioIn); @try { id symIdx = [wWithProp valueForKey:@"symbolIndex"]; printf(" _ANEIOSurfaceObject.symbolIndex after IOSurface property set: %s\n", symIdx ? [[symIdx description] UTF8String] : "nil"); if (symIdx) R.got_symbol_index = true; } @catch (NSException *ex) { printf(" _ANEIOSurfaceObject.symbolIndex: \n", [[ex reason] UTF8String]); } } // 3e: Try _ANEProgramForEvaluation // API: +programWithHandle:(uint64_t)handle intermediateBufferHandle:(uint64_t)ibh queueDepth:(char)qd // +programWithController:(id)ctrl intermediateBufferHandle:(uint64_t)ibh queueDepth:(char)qd Class gProgEval = NSClassFromString(@"_ANEProgramForEvaluation"); if (gProgEval) { printf("\n --- 3e: _ANEProgramForEvaluation ---\n"); // The model already has a .program property -- read it directly @try { id existingProg = [k1.model valueForKey:@"program"]; printf(" k1.model.program: %s\n", existingProg ? [[existingProg description] UTF8String] : "nil"); if (existingProg) { dump_all_properties(existingProg, gProgEval); } } @catch (NSException *ex) { printf(" k1.model.program: \n", [[ex reason] UTF8String]); } // Try programWithHandle:intermediateBufferHandle:queueDepth: uint64_t ibHandle = 0; @try { id ibh = [k1.model valueForKey:@"intermediateBufferHandle"]; if (ibh) ibHandle = [ibh unsignedLongLongValue]; } @catch (NSException *ex) { (void)ex; } @try { id prog = ((id(*)(Class,SEL,uint64_t,uint64_t,char))objc_msgSend)(gProgEval, @selector(programWithHandle:intermediateBufferHandle:queueDepth:), progHandle, ibHandle, (char)1); printf(" programWithHandle(%llu, %llu, 1): %s\n", progHandle, ibHandle, prog ? [[prog description] UTF8String] : "nil"); if (prog) dump_all_properties(prog, gProgEval); } @catch (NSException *ex) { printf(" programWithHandle EXCEPTION: %s\n", [[ex reason] UTF8String]); } } // 3f: Try _ANEIOSurfaceOutputSets and _ANEInputBuffersReady const char *chain_helper_classes[] = { "_ANEIOSurfaceOutputSets", "_ANEInputBuffersReady", "_ANEOutputSetEnqueue", NULL }; for (int ci = 0; chain_helper_classes[ci]; ci++) { Class cls = NSClassFromString([NSString stringWithUTF8String:chain_helper_classes[ci]]); if (!cls) continue; printf("\n --- 3f: %s instantiation ---\n", chain_helper_classes[ci]); unsigned int mc = 0; Method *ms = class_copyMethodList(object_getClass(cls), &mc); for (unsigned int i = 0; i < mc; i++) { SEL s = method_getName(ms[i]); printf(" + %s\n", sel_getName(s)); } free(ms); @try { id obj = [[cls alloc] init]; printf(" alloc/init: %s\n", obj ? [[obj description] UTF8String] : "nil"); if (obj) dump_all_properties(obj, cls); } @catch (NSException *ex) { printf(" alloc/init EXCEPTION: %s\n", [[ex reason] UTF8String]); } } R.phase3_done = true; printf("\n Phase 3 complete: mapper=%s buffer=%s symbolIndex=%s\n", R.mapper_works ? "YES" : "NO", R.buffer_works ? "YES" : "NO", R.got_symbol_index ? "YES" : "NO"); // ===================================================================== // PHASE 4: ChainingRequest with (potentially) indexed surfaces // ===================================================================== printf("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); printf(" PHASE 4: ChainingRequest Retry\n"); printf("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); // 4a: Sequential baseline printf("\n --- 4a: Sequential baseline ---\n"); int WARMUP = 5, ITERS = 50; for (int i = 0; i < WARMUP; i++) { ((BOOL(*)(id,SEL,unsigned int,id,id,NSError**))objc_msgSend)( k1.model, @selector(evaluateWithQoS:options:request:error:), 21, @{}, req1, &e); IOSurfaceLock(k1.ioOut, 0, NULL); memcpy(IOSurfaceGetBaseAddress(k2.ioIn), IOSurfaceGetBaseAddress(k1.ioOut), ioBytes); IOSurfaceUnlock(k1.ioOut, 0, NULL); ((BOOL(*)(id,SEL,unsigned int,id,id,NSError**))objc_msgSend)( k2.model, @selector(evaluateWithQoS:options:request:error:), 21, @{}, req2, &e); } uint64_t t0 = mach_absolute_time(); for (int i = 0; i < ITERS; i++) { ((BOOL(*)(id,SEL,unsigned int,id,id,NSError**))objc_msgSend)( k1.model, @selector(evaluateWithQoS:options:request:error:), 21, @{}, req1, &e); IOSurfaceLock(k1.ioOut, 0, NULL); memcpy(IOSurfaceGetBaseAddress(k2.ioIn), IOSurfaceGetBaseAddress(k1.ioOut), ioBytes); IOSurfaceUnlock(k1.ioOut, 0, NULL); ((BOOL(*)(id,SEL,unsigned int,id,id,NSError**))objc_msgSend)( k2.model, @selector(evaluateWithQoS:options:request:error:), 21, @{}, req2, &e); } R.sequential_ms = tb_ms(mach_absolute_time() - t0) / ITERS; printf(" Sequential: %.3f ms/pair (%d iters)\n", R.sequential_ms, ITERS); IOSurfaceLock(k2.ioOut, kIOSurfaceLockReadOnly, NULL); if (g_fp16_io) { _Float16 *out = (_Float16*)IOSurfaceGetBaseAddress(k2.ioOut); printf(" Output[0..3]: [%.4f, %.4f, %.4f, %.4f]\n", (float)out[0], (float)out[1], (float)out[2], (float)out[3]); } else { float *out = (float*)IOSurfaceGetBaseAddress(k2.ioOut); printf(" Output[0..3]: [%.4f, %.4f, %.4f, %.4f]\n", out[0], out[1], out[2], out[3]); } IOSurfaceUnlock(k2.ioOut, kIOSurfaceLockReadOnly, NULL); // 4b: ChainingRequest attempts printf("\n --- 4b: ChainingRequest attempts ---\n"); id client = nil; if (gClient) { client = [gClient performSelector:@selector(sharedConnection)]; printf(" _ANEClient: %s\n", client ? "obtained" : "FAILED"); } if (gChain && client) { // Attempt 1: standard (same as v1) printf("\n [Attempt 1] Standard ChainingRequest (raw IOSurface objects)\n"); @try { id chainReq = ((id(*)(Class,SEL,id,id,id,id,id,id,id,id,id))objc_msgSend)(gChain, @selector(chainingRequestWithInputs:outputSets:lbInputSymbolId:lbOutputSymbolId:procedureIndex:signalEvents:transactionHandle:fwEnqueueDelay:memoryPoolId:), @[wI1], @[@[wO1]], @[@0], @[@0], @0, @[], @0, @0, @0); if (chainReq) { BOOL valid = ((BOOL(*)(id,SEL))objc_msgSend)(chainReq, @selector(validate)); printf(" created: YES | validate: %s\n", valid ? "YES" : "NO"); R.validate_passed = valid; if (valid && client) { @try { BOOL prep = ((BOOL(*)(id,SEL,id,id,id,unsigned int,NSError**))objc_msgSend)( client, @selector(prepareChainingWithModel:options:chainingReq:qos:error:), k1.model, @{}, chainReq, 21, &e); printf(" prepareChainingWithModel: %s\n", prep ? "YES" : "NO"); if (!prep && e) printf(" error: %s\n", [[e description] UTF8String]); } @catch (NSException *ex) { printf(" prepareChainingWithModel EXCEPTION: %s\n", [[ex reason] UTF8String]); } } } else { printf(" created: NO\n"); } } @catch (NSException *ex) { printf(" EXCEPTION: %s\n", [[ex reason] UTF8String]); } // Attempt 2: with IOSurface property "symbolIndex" printf("\n [Attempt 2] IOSurface with symbolIndex property\n"); @try { IOSurfaceRef sIn = make_surface(ioBytes); IOSurfaceRef sOut = make_surface(ioBytes); IOSurfaceLock(sIn, 0, NULL); if (g_fp16_io) { _Float16 *inp = (_Float16*)IOSurfaceGetBaseAddress(sIn); for (int i = 0; i < CH*SP; i++) inp[i] = (_Float16)1.0f; } else { float *inp = (float*)IOSurfaceGetBaseAddress(sIn); for (int i = 0; i < CH*SP; i++) inp[i] = 1.0f; } IOSurfaceSetValue(sIn, CFSTR("symbolIndex"), (__bridge CFTypeRef)@0); IOSurfaceUnlock(sIn, 0, NULL); IOSurfaceLock(sOut, 0, NULL); IOSurfaceSetValue(sOut, CFSTR("symbolIndex"), (__bridge CFTypeRef)@0); IOSurfaceUnlock(sOut, 0, NULL); id wIn2 = ((id(*)(Class,SEL,IOSurfaceRef))objc_msgSend)(gAIO, @selector(objectWithIOSurface:), sIn); id wOut2 = ((id(*)(Class,SEL,IOSurfaceRef))objc_msgSend)(gAIO, @selector(objectWithIOSurface:), sOut); id chainReq2 = ((id(*)(Class,SEL,id,id,id,id,id,id,id,id,id))objc_msgSend)(gChain, @selector(chainingRequestWithInputs:outputSets:lbInputSymbolId:lbOutputSymbolId:procedureIndex:signalEvents:transactionHandle:fwEnqueueDelay:memoryPoolId:), @[wIn2], @[@[wOut2]], @[@0], @[@0], @0, @[], @0, @0, @0); if (chainReq2) { BOOL valid = ((BOOL(*)(id,SEL))objc_msgSend)(chainReq2, @selector(validate)); printf(" created: YES | validate: %s\n", valid ? "YES" : "NO"); if (valid) R.validate_passed = true; if (valid) { @try { BOOL prep = ((BOOL(*)(id,SEL,id,id,id,unsigned int,NSError**))objc_msgSend)( client, @selector(prepareChainingWithModel:options:chainingReq:qos:error:), k1.model, @{}, chainReq2, 21, &e); printf(" prepareChainingWithModel: %s\n", prep ? "YES" : "NO"); if (prep) R.chaining_executed = true; } @catch (NSException *ex) { printf(" prepareChainingWithModel EXCEPTION: %s\n", [[ex reason] UTF8String]); } } } CFRelease(sIn); CFRelease(sOut); } @catch (NSException *ex) { printf(" EXCEPTION: %s\n", [[ex reason] UTF8String]); } // Attempt 3: two-model loopback with output sets printf("\n [Attempt 3] Two-model loopback with multiple output sets\n"); @try { IOSurfaceRef sMid = make_surface(ioBytes); id wMid = ((id(*)(Class,SEL,IOSurfaceRef))objc_msgSend)(gAIO, @selector(objectWithIOSurface:), sMid); id chainLoop = ((id(*)(Class,SEL,id,id,id,id,id,id,id,id,id))objc_msgSend)(gChain, @selector(chainingRequestWithInputs:outputSets:lbInputSymbolId:lbOutputSymbolId:procedureIndex:signalEvents:transactionHandle:fwEnqueueDelay:memoryPoolId:), @[wI1], @[@[wMid], @[wO2]], @[@0], @[@0], @0, @[], @0, @0, @0); if (chainLoop) { BOOL valid = ((BOOL(*)(id,SEL))objc_msgSend)(chainLoop, @selector(validate)); printf(" created: YES | validate: %s\n", valid ? "YES" : "NO"); @try { BOOL prep = ((BOOL(*)(id,SEL,id,id,id,unsigned int,NSError**))objc_msgSend)( client, @selector(prepareChainingWithModel:options:chainingReq:qos:error:), k1.model, @{}, chainLoop, 21, &e); printf(" prepareChainingWithModel: %s\n", prep ? "YES" : "NO"); if (!prep && e) printf(" error: %s\n", [[e description] UTF8String]); if (prep) { R.chaining_executed = true; uint64_t tc0 = mach_absolute_time(); for (int i = 0; i < ITERS; i++) { BOOL enq = ((BOOL(*)(id,SEL,id,id,id,unsigned int,NSError**))objc_msgSend)( client, @selector(enqueueSetsWithModel:outputSet:options:qos:error:), k1.model, @[wMid], @{}, 21, &e); (void)enq; BOOL buf = ((BOOL(*)(id,SEL,id,id,id,unsigned int,NSError**))objc_msgSend)( client, @selector(buffersReadyWithModel:inputBuffers:options:qos:error:), k1.model, @[wI1], @{}, 21, &e); (void)buf; } R.chained_ms = tb_ms(mach_absolute_time() - tc0) / ITERS; printf(" Chained: %.3f ms/pair (%d iters)\n", R.chained_ms, ITERS); printf(" Speedup: %.2fx vs sequential\n", R.sequential_ms / R.chained_ms); } } @catch (NSException *ex) { printf(" EXCEPTION: %s\n", [[ex reason] UTF8String]); } } CFRelease(sMid); } @catch (NSException *ex) { printf(" EXCEPTION: %s\n", [[ex reason] UTF8String]); } // Attempt 4: force validate bypass via prepareChainingWithModel directly printf("\n [Attempt 4] Skip validate, call prepareChainingWithModel directly\n"); @try { id chainDirect = ((id(*)(Class,SEL,id,id,id,id,id,id,id,id,id))objc_msgSend)(gChain, @selector(chainingRequestWithInputs:outputSets:lbInputSymbolId:lbOutputSymbolId:procedureIndex:signalEvents:transactionHandle:fwEnqueueDelay:memoryPoolId:), @[wI1], @[@[wO1]], @[@0], @[@0], @0, @[], @0, @0, @0); if (chainDirect) { BOOL prep = ((BOOL(*)(id,SEL,id,id,id,unsigned int,NSError**))objc_msgSend)( client, @selector(prepareChainingWithModel:options:chainingReq:qos:error:), k1.model, @{}, chainDirect, 21, &e); printf(" prepareChainingWithModel (no validate): %s\n", prep ? "YES" : "NO"); if (!prep && e) printf(" error: %s\n", [[e description] UTF8String]); if (prep) { R.chaining_executed = true; @try { BOOL enq = ((BOOL(*)(id,SEL,id,id,id,unsigned int,NSError**))objc_msgSend)( client, @selector(enqueueSetsWithModel:outputSet:options:qos:error:), k1.model, @[wO1], @{}, 21, &e); printf(" enqueueSets: %s\n", enq ? "YES" : "NO"); if (!enq && e) printf(" error: %s\n", [[e description] UTF8String]); } @catch (NSException *ex) { printf(" enqueueSets EXCEPTION: %s\n", [[ex reason] UTF8String]); } @try { BOOL buf = ((BOOL(*)(id,SEL,id,id,id,unsigned int,NSError**))objc_msgSend)( client, @selector(buffersReadyWithModel:inputBuffers:options:qos:error:), k1.model, @[wI1], @{}, 21, &e); printf(" buffersReady: %s\n", buf ? "YES" : "NO"); if (!buf && e) printf(" error: %s\n", [[e description] UTF8String]); } @catch (NSException *ex) { printf(" buffersReady EXCEPTION: %s\n", [[ex reason] UTF8String]); } } } } @catch (NSException *ex) { printf(" EXCEPTION: %s\n", [[ex reason] UTF8String]); } // Attempt 5: Use _ANEBuffer inputs + _ANEIOSurfaceOutputSets for outputSets printf("\n [Attempt 5] ChainingRequest with _ANEBuffer + _ANEIOSurfaceOutputSets\n"); { Class gOutSets = NSClassFromString(@"_ANEIOSurfaceOutputSets"); if (gBuffer && gOutSets) { @try { id bufIn = ((id(*)(Class,SEL,id,id,long long))objc_msgSend)(gBuffer, @selector(bufferWithIOSurfaceObject:symbolIndex:source:), wI1, @0, (long long)0); id bufOut = ((id(*)(Class,SEL,id,id,long long))objc_msgSend)(gBuffer, @selector(bufferWithIOSurfaceObject:symbolIndex:source:), wO1, @0, (long long)1); printf(" bufIn: %s\n", bufIn ? [[bufIn description] UTF8String] : "nil"); printf(" bufOut: %s\n", bufOut ? [[bufOut description] UTF8String] : "nil"); // Create _ANEIOSurfaceOutputSets: +objectWithstatsSurRef:outputBuffer: // statsSurRef can be NULL, outputBuffer is NSArray of _ANEBuffer id outSet = ((id(*)(Class,SEL,IOSurfaceRef,id))objc_msgSend)(gOutSets, @selector(objectWithstatsSurRef:outputBuffer:), NULL, @[bufOut]); printf(" outputSet: %s\n", outSet ? [[outSet description] UTF8String] : "nil"); if (bufIn && outSet) { id chainBuf = ((id(*)(Class,SEL,id,id,id,id,id,id,id,id,id))objc_msgSend)(gChain, @selector(chainingRequestWithInputs:outputSets:lbInputSymbolId:lbOutputSymbolId:procedureIndex:signalEvents:transactionHandle:fwEnqueueDelay:memoryPoolId:), @[bufIn], @[outSet], @[@0], @[@0], @0, @[], @0, @0, @0); if (chainBuf) { BOOL valid = ((BOOL(*)(id,SEL))objc_msgSend)(chainBuf, @selector(validate)); printf(" created: YES | validate: %s\n", valid ? "YES" : "NO"); if (valid) R.validate_passed = true; @try { BOOL prep = ((BOOL(*)(id,SEL,id,id,id,unsigned int,NSError**))objc_msgSend)( client, @selector(prepareChainingWithModel:options:chainingReq:qos:error:), k1.model, @{}, chainBuf, 21, &e); printf(" prepareChainingWithModel: %s\n", prep ? "YES" : "NO"); if (!prep && e) printf(" error: %s\n", [[e description] UTF8String]); if (prep) R.chaining_executed = true; } @catch (NSException *ex) { printf(" prepareChainingWithModel EXCEPTION: %s\n", [[ex reason] UTF8String]); } } else { printf(" ChainingRequest creation: nil\n"); } } } @catch (NSException *ex) { printf(" EXCEPTION: %s\n", [[ex reason] UTF8String]); } } else { printf(" _ANEBuffer or _ANEIOSurfaceOutputSets not available\n"); } } // Attempt 6: Use _ANEClient.evaluateWithModel (5-param variant) printf("\n [Attempt 6] _ANEClient.evaluateWithModel:options:request:qos:error:\n"); @try { BOOL clientEval = ((BOOL(*)(id,SEL,id,id,id,unsigned int,NSError**))objc_msgSend)( client, @selector(evaluateWithModel:options:request:qos:error:), k1.model, @{}, req1, 21, &e); printf(" evaluateWithModel (via client): %s\n", clientEval ? "YES" : "NO"); if (!clientEval && e) printf(" error: %s\n", [[e description] UTF8String]); } @catch (NSException *ex) { printf(" EXCEPTION: %s\n", [[ex reason] UTF8String]); } // Attempt 7: Use _ANEClient.doEvaluateDirectWithModel printf("\n [Attempt 7] _ANEClient.doEvaluateDirectWithModel\n"); @try { BOOL directEval = ((BOOL(*)(id,SEL,id,id,id,unsigned int,NSError**))objc_msgSend)( client, @selector(doEvaluateDirectWithModel:options:request:qos:error:), k1.model, @{}, req1, 21, &e); printf(" doEvaluateDirectWithModel: %s\n", directEval ? "YES" : "NO"); if (!directEval && e) printf(" error: %s\n", [[e description] UTF8String]); } @catch (NSException *ex) { printf(" EXCEPTION: %s\n", [[ex reason] UTF8String]); } } else { printf(" Skipped: gChain=%s client=%s\n", gChain ? "YES" : "NO", client ? "YES" : "NO"); } R.phase4_done = true; // ===================================================================== // PHASE 5: Alternative Execution Paths // ===================================================================== printf("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); printf(" PHASE 5: Alternative Execution Paths\n"); printf("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); // 5a: Real-time eval printf("\n --- 5a: Real-time eval path ---\n"); if (client) { @try { printf(" Calling beginRealTimeTask...\n"); BOOL rtBegin = ((BOOL(*)(id,SEL))objc_msgSend)(client, @selector(beginRealTimeTask)); printf(" beginRealTimeTask: %s\n", rtBegin ? "YES" : "NO"); printf(" Calling evaluateRealTimeWithModel...\n"); BOOL rtOk = ((BOOL(*)(id,SEL,id,id,id,NSError**))objc_msgSend)( client, @selector(evaluateRealTimeWithModel:options:request:error:), k1.model, @{}, req1, &e); printf(" evaluateRealTimeWithModel: %s\n", rtOk ? "YES" : "NO"); if (!rtOk && e) printf(" error: %s\n", [[e description] UTF8String]); R.realtime_eval_works = rtOk; if (rtOk) { double rt_times[ITERS]; for (int i = 0; i < WARMUP; i++) { ((BOOL(*)(id,SEL,id,id,id,NSError**))objc_msgSend)( client, @selector(evaluateRealTimeWithModel:options:request:error:), k1.model, @{}, req1, &e); } for (int i = 0; i < ITERS; i++) { uint64_t ti = mach_absolute_time(); ((BOOL(*)(id,SEL,id,id,id,NSError**))objc_msgSend)( client, @selector(evaluateRealTimeWithModel:options:request:error:), k1.model, @{}, req1, &e); rt_times[i] = tb_ms(mach_absolute_time() - ti); } double rt_sum = 0; for (int i = 0; i < ITERS; i++) rt_sum += rt_times[i]; printf(" RT eval: %.3f ms/eval avg (%d iters)\n", rt_sum/ITERS, ITERS); double std_times[ITERS]; for (int i = 0; i < ITERS; i++) { uint64_t ti = mach_absolute_time(); ((BOOL(*)(id,SEL,unsigned int,id,id,NSError**))objc_msgSend)( k1.model, @selector(evaluateWithQoS:options:request:error:), 21, @{}, req1, &e); std_times[i] = tb_ms(mach_absolute_time() - ti); } double std_sum = 0; for (int i = 0; i < ITERS; i++) std_sum += std_times[i]; printf(" Standard eval: %.3f ms/eval avg (%d iters)\n", std_sum/ITERS, ITERS); printf(" RT vs Standard speedup: %.2fx\n", (std_sum/ITERS) / (rt_sum/ITERS)); } BOOL rtEnd = ((BOOL(*)(id,SEL))objc_msgSend)(client, @selector(endRealTimeTask)); printf(" endRealTimeTask: %s\n", rtEnd ? "YES" : "NO"); } @catch (NSException *ex) { printf(" Real-time eval EXCEPTION: %s\n", [[ex reason] UTF8String]); } } // 5b: PerfStats with perfStatsMask printf("\n --- 5b: PerfStats with perfStatsMask ---\n"); { Class perfClass = NSClassFromString(@"_ANEPerformanceStats"); if (perfClass) { @try { printf(" Setting perfStatsMask on model...\n"); for (unsigned int mask = 1; mask <= 0xFF; mask <<= 1) { @try { [k1.model setValue:@(mask) forKey:@"perfStatsMask"]; printf(" perfStatsMask = 0x%02X: set OK\n", mask); } @catch (NSException *ex) { printf(" perfStatsMask = 0x%02X: \n", mask, [[ex reason] UTF8String]); break; } } } @catch (NSException *ex) { printf(" perfStatsMask setter: \n", [[ex reason] UTF8String]); } id perfStats = nil; @try { perfStats = ((id(*)(Class,SEL,uint64_t))objc_msgSend)(perfClass, @selector(statsWithHardwareExecutionNS:), (uint64_t)0); printf(" statsWithHardwareExecutionNS:0 = %s\n", perfStats ? [[perfStats description] UTF8String] : "nil"); } @catch (NSException *ex) { printf(" statsWithHardwareExecutionNS: EXCEPTION: %s\n", [[ex reason] UTF8String]); } if (!perfStats) { @try { perfStats = [[perfClass alloc] init]; printf(" alloc/init fallback = %s\n", perfStats ? [[perfStats description] UTF8String] : "nil"); } @catch (NSException *ex) { printf(" alloc/init EXCEPTION: %s\n", [[ex reason] UTF8String]); } } if (perfStats) { // perfStats param expects NSArray (request calls [perfStats count]) // Try wrapping in array, and also try with nil + perfStatsMask printf(" Test A: perfStats as NSArray wrapper\n"); @try { id reqPerfA = ((id(*)(Class,SEL,id,id,id,id,id,id,id))objc_msgSend)(gAR, @selector(requestWithInputs:inputIndices:outputs:outputIndices:weightsBuffer:perfStats:procedureIndex:), @[wI1], @[@0], @[wO1], @[@0], nil, @[perfStats], @0); if (reqPerfA) { BOOL ok = ((BOOL(*)(id,SEL,unsigned int,id,id,NSError**))objc_msgSend)( k1.model, @selector(evaluateWithQoS:options:request:error:), 21, @{}, reqPerfA, &e); printf(" Eval with @[perfStats]: %s\n", ok ? "OK" : "FAIL"); if (ok) { printf(" PerfStats after eval:\n"); dump_all_properties(perfStats, perfClass); @try { id hwTime = [perfStats valueForKey:@"hwExecutionTime"]; printf(" hwExecutionTime = %s\n", hwTime ? [[hwTime description] UTF8String] : "nil"); if (hwTime) { R.hw_exec_time_ns = [hwTime unsignedLongLongValue]; R.perfstats_works = (R.hw_exec_time_ns > 0); } } @catch (NSException *ex) { printf(" hwExecutionTime: \n"); } } } } @catch (NSException *ex) { printf(" Test A EXCEPTION: %s\n", [[ex reason] UTF8String]); } // Test B: perfStatsMask set, but perfStats=nil in request printf(" Test B: perfStatsMask=0xFF, perfStats=nil\n"); @try { [k1.model setValue:@(0xFF) forKey:@"perfStatsMask"]; id reqPerfB = ((id(*)(Class,SEL,id,id,id,id,id,id,id))objc_msgSend)(gAR, @selector(requestWithInputs:inputIndices:outputs:outputIndices:weightsBuffer:perfStats:procedureIndex:), @[wI1], @[@0], @[wO1], @[@0], nil, nil, @0); BOOL ok = ((BOOL(*)(id,SEL,unsigned int,id,id,NSError**))objc_msgSend)( k1.model, @selector(evaluateWithQoS:options:request:error:), 21, @{}, reqPerfB, &e); printf(" Eval with mask=0xFF, perfStats=nil: %s\n", ok ? "OK" : "FAIL"); uint64_t psMask = [[k1.model valueForKey:@"perfStatsMask"] unsignedIntValue]; printf(" perfStatsMask after eval: 0x%llX\n", (unsigned long long)psMask); } @catch (NSException *ex) { printf(" Test B EXCEPTION: %s\n", [[ex reason] UTF8String]); } @try { id counters = [perfStats performSelector:@selector(performanceCounters)]; printf(" performanceCounters: %s\n", counters ? [[counters description] UTF8String] : "nil"); } @catch (NSException *ex) { printf(" performanceCounters: \n", [[ex reason] UTF8String]); } } } else { printf(" _ANEPerformanceStats: NOT FOUND\n"); } } R.phase5_done = true; // ===================================================================== // PHASE 7 (Exp A): _ANEIOSurfaceOutputSets with non-NULL statsSurRef // ===================================================================== printf("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); printf(" PHASE 7: OutputSets with stats IOSurface\n"); printf("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); { Class gOutSets = NSClassFromString(@"_ANEIOSurfaceOutputSets"); Class gBuf = NSClassFromString(@"_ANEBuffer"); if (gOutSets && gBuf) { id bufOut7 = ((id(*)(Class,SEL,id,id,long long))objc_msgSend)(gBuf, @selector(bufferWithIOSurfaceObject:symbolIndex:source:), wO1, @0, (long long)1); size_t stats_sizes[] = {64, 256, 1024, 4096, 16384}; for (int si = 0; si < 5; si++) { IOSurfaceRef statsSurf = make_surface(stats_sizes[si]); printf("\n statsSurRef size=%zu bytes:\n", stats_sizes[si]); @try { id outSet = ((id(*)(Class,SEL,IOSurfaceRef,id))objc_msgSend)(gOutSets, @selector(objectWithstatsSurRef:outputBuffer:), statsSurf, @[bufOut7]); printf(" objectWithstatsSurRef: %s\n", outSet ? [[outSet description] UTF8String] : "nil"); if (outSet) { R.outputsets_with_stats_works = true; dump_all_properties(outSet, gOutSets); printf("\n Attempting ChainingRequest with valid outputSet...\n"); id bufIn7 = ((id(*)(Class,SEL,id,id,long long))objc_msgSend)(gBuf, @selector(bufferWithIOSurfaceObject:symbolIndex:source:), wI1, @0, (long long)0); @try { id chain7 = ((id(*)(Class,SEL,id,id,id,id,id,id,id,id,id))objc_msgSend)(gChain, @selector(chainingRequestWithInputs:outputSets:lbInputSymbolId:lbOutputSymbolId:procedureIndex:signalEvents:transactionHandle:fwEnqueueDelay:memoryPoolId:), @[bufIn7], @[outSet], @[@0], @[@0], @0, @[], @0, @0, @0); if (chain7) { BOOL valid7 = ((BOOL(*)(id,SEL))objc_msgSend)(chain7, @selector(validate)); printf(" ChainingRequest created | validate: %s\n", valid7 ? "YES" : "NO"); if (valid7) R.chaining_with_stats_works = true; @try { BOOL prep7 = ((BOOL(*)(id,SEL,id,id,id,unsigned int,NSError**))objc_msgSend)( client, @selector(prepareChainingWithModel:options:chainingReq:qos:error:), k1.model, @{}, chain7, 21, &e); printf(" prepareChainingWithModel: %s\n", prep7 ? "YES" : "NO"); if (!prep7 && e) printf(" error: %s\n", [[e description] UTF8String]); if (prep7) R.chaining_with_stats_works = true; } @catch (NSException *ex) { printf(" prepareChainingWithModel EXCEPTION: %s\n", [[ex reason] UTF8String]); } } else { printf(" ChainingRequest creation: nil\n"); } } @catch (NSException *ex) { printf(" ChainingRequest EXCEPTION: %s\n", [[ex reason] UTF8String]); } } } @catch (NSException *ex) { printf(" EXCEPTION: %s\n", [[ex reason] UTF8String]); } CFRelease(statsSurf); if (R.outputsets_with_stats_works) break; } } else { printf(" Required classes not found\n"); } } R.phase7_done = true; // ===================================================================== // PHASE 8 (Exp B): Disk-based _ANEModel for symbol discovery // ===================================================================== printf("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); printf(" PHASE 8: Disk-based _ANEModel path\n"); printf("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); { Class gANEModel = NSClassFromString(@"_ANEModel"); if (gANEModel) { printf("\n _ANEModel class found. Dumping API surface...\n"); dump_class("_ANEModel"); NSString *compiledPath = nil; @try { compiledPath = [k1.model valueForKey:@"compiledModelPath"]; printf(" k1.compiledModelPath: %s\n", compiledPath ? [compiledPath UTF8String] : "nil"); } @catch (NSException *ex) { printf(" compiledModelPath: \n"); } if (!compiledPath) { @try { id url = [k1.model valueForKey:@"compiledModelURL"]; if (url) compiledPath = [url path]; printf(" k1.compiledModelURL.path: %s\n", compiledPath ? [compiledPath UTF8String] : "nil"); } @catch (NSException *ex) { printf(" compiledModelURL: \n"); } } NSString *modelDir = k1.tmpDir; printf(" k1.tmpDir: %s\n", [modelDir UTF8String]); NSFileManager *fm8 = [NSFileManager defaultManager]; NSArray *contents = [fm8 contentsOfDirectoryAtPath:modelDir error:nil]; printf(" tmpDir contents: %s\n", contents ? [[contents description] UTF8String] : "empty"); SEL factorySelectors[] = { @selector(modelAtURL:), @selector(modelWithPath:), NSSelectorFromString(@"modelAtPath:"), NSSelectorFromString(@"modelWithURL:"), }; const char *factoryNames[] = {"modelAtURL:", "modelWithPath:", "modelAtPath:", "modelWithURL:"}; for (int fi = 0; fi < 4; fi++) { if ([gANEModel respondsToSelector:factorySelectors[fi]]) { printf(" +%s: available\n", factoryNames[fi]); } else { printf(" +%s: NOT available\n", factoryNames[fi]); } } id diskModel = nil; @try { if ([gANEModel respondsToSelector:@selector(modelAtURL:)]) { NSURL *dirURL = [NSURL fileURLWithPath:modelDir]; diskModel = ((id(*)(Class,SEL,id))objc_msgSend)(gANEModel, @selector(modelAtURL:), dirURL); printf(" modelAtURL: %s\n", diskModel ? [[diskModel description] UTF8String] : "nil"); } } @catch (NSException *ex) { printf(" modelAtURL EXCEPTION: %s\n", [[ex reason] UTF8String]); } if (!diskModel) { @try { SEL s = NSSelectorFromString(@"modelAtPath:"); if ([gANEModel respondsToSelector:s]) { diskModel = ((id(*)(Class,SEL,id))objc_msgSend)(gANEModel, s, modelDir); printf(" modelAtPath: %s\n", diskModel ? [[diskModel description] UTF8String] : "nil"); } } @catch (NSException *ex) { printf(" modelAtPath EXCEPTION: %s\n", [[ex reason] UTF8String]); } } if (diskModel) { R.disk_model_loads = true; printf("\n _ANEModel loaded! Querying symbol names...\n"); dump_all_properties(diskModel, gANEModel); const char *symbol_keys[] = { "inputSymbolNames", "outputSymbolNames", "inputSymbolIndicesForProcedureIndex:", "outputSymbolIndicesForProcedureIndex:", NULL }; for (int ki = 0; symbol_keys[ki]; ki++) { @try { if (strchr(symbol_keys[ki], ':')) { SEL s = NSSelectorFromString( [NSString stringWithUTF8String:symbol_keys[ki]]); if ([diskModel respondsToSelector:s]) { id result = ((id(*)(id,SEL,NSUInteger))objc_msgSend)( diskModel, s, (NSUInteger)0); printf(" %s(0) = %s\n", symbol_keys[ki], result ? [[result description] UTF8String] : "nil"); R.disk_model_has_symbols = (result != nil); } else { printf(" %s: NOT available\n", symbol_keys[ki]); } } else { id val = [diskModel valueForKey: [NSString stringWithUTF8String:symbol_keys[ki]]]; printf(" %s = %s\n", symbol_keys[ki], val ? [[val description] UTF8String] : "nil"); if (val) R.disk_model_has_symbols = true; } } @catch (NSException *ex) { printf(" %s: \n", symbol_keys[ki], [[ex reason] UTF8String]); } } } else { printf(" _ANEModel could not be loaded from tmpDir\n"); } } else { printf(" _ANEModel: NOT FOUND\n"); } } R.phase8_done = true; // ===================================================================== // PHASE 9 (Exp C): processRequest via _ANEProgramForEvaluation // ===================================================================== printf("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); printf(" PHASE 9: processRequest via ProgramForEvaluation\n"); printf("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); { @try { id prog = [k1.model valueForKey:@"program"]; if (prog) { printf(" k1.model.program: %s\n", [[prog description] UTF8String]); id hexId = [k1.model valueForKey:@"hexStringIdentifier"]; printf(" hexStringIdentifier: %s\n", hexId ? [[hexId description] UTF8String] : "nil"); SEL procSel = @selector(processRequest:model:qos:qIndex:modelStringID:options:returnValue:error:); if ([prog respondsToSelector:procSel]) { printf(" processRequest selector: available\n"); for (int warmup = 0; warmup < WARMUP; warmup++) { @try { BOOL rv = NO; ((BOOL(*)(id,SEL,id,id,unsigned int,int,id,id,BOOL*,NSError**))objc_msgSend)( prog, procSel, req1, k1.model, 21, 0, hexId, @{}, &rv, &e); } @catch (NSException *ex) { (void)ex; } } BOOL firstOk = NO; @try { BOOL rv = NO; firstOk = ((BOOL(*)(id,SEL,id,id,unsigned int,int,id,id,BOOL*,NSError**))objc_msgSend)( prog, procSel, req1, k1.model, 21, 0, hexId, @{}, &rv, &e); printf(" processRequest single call: %s (rv=%s)\n", firstOk ? "YES" : "NO", rv ? "YES" : "NO"); if (!firstOk && e) printf(" error: %s\n", [[e description] UTF8String]); } @catch (NSException *ex) { printf(" processRequest EXCEPTION: %s\n", [[ex reason] UTF8String]); } if (firstOk) { R.process_request_works = true; uint64_t t9 = mach_absolute_time(); for (int i = 0; i < ITERS; i++) { BOOL rv = NO; ((BOOL(*)(id,SEL,id,id,unsigned int,int,id,id,BOOL*,NSError**))objc_msgSend)( prog, procSel, req1, k1.model, 21, 0, hexId, @{}, &rv, &e); } R.process_request_ms = tb_ms(mach_absolute_time() - t9) / ITERS; printf(" processRequest: %.3f ms/eval (%d iters)\n", R.process_request_ms, ITERS); printf(" vs RT eval: %.2fx\n", R.process_request_ms / (R.rt_eval_ms > 0 ? R.rt_eval_ms : 0.090)); } } else { printf(" processRequest selector: NOT available\n"); } } else { printf(" k1.model.program: nil\n"); } } @catch (NSException *ex) { printf(" EXCEPTION: %s\n", [[ex reason] UTF8String]); } } R.phase9_done = true; // ===================================================================== // PHASE 10 (Exp D): Shared Events for hardware synchronization // ===================================================================== printf("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); printf(" PHASE 10: Shared Events (hardware sync)\n"); printf("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); { const char *event_classes[] = { "_ANESharedEvents", "_ANESharedSignalEvent", "_ANESharedWaitEvent", NULL }; for (int ei = 0; event_classes[ei]; ei++) { Class cls = NSClassFromString([NSString stringWithUTF8String:event_classes[ei]]); if (cls) { R.shared_events_exist = true; dump_class(event_classes[ei]); @try { id obj = [[cls alloc] init]; printf(" %s alloc/init: %s\n", event_classes[ei], obj ? [[obj description] UTF8String] : "nil"); if (obj) dump_all_properties(obj, cls); } @catch (NSException *ex) { printf(" %s alloc/init EXCEPTION: %s\n", event_classes[ei], [[ex reason] UTF8String]); } } else { printf(" %s: NOT FOUND\n", event_classes[ei]); } } if (R.shared_events_exist && gChain && client) { printf("\n Attempting ChainingRequest with shared events...\n"); Class sigCls = NSClassFromString(@"_ANESharedSignalEvent"); Class waitCls = NSClassFromString(@"_ANESharedWaitEvent"); if (sigCls && waitCls) { @try { id sigEvent = [[sigCls alloc] init]; id waitEvent = [[waitCls alloc] init]; printf(" signalEvent: %s\n", sigEvent ? [[sigEvent description] UTF8String] : "nil"); printf(" waitEvent: %s\n", waitEvent ? [[waitEvent description] UTF8String] : "nil"); if (sigEvent) { Class gBuf = NSClassFromString(@"_ANEBuffer"); id bufIn10 = ((id(*)(Class,SEL,id,id,long long))objc_msgSend)(gBuf, @selector(bufferWithIOSurfaceObject:symbolIndex:source:), wI1, @0, (long long)0); id chain10 = ((id(*)(Class,SEL,id,id,id,id,id,id,id,id,id))objc_msgSend)(gChain, @selector(chainingRequestWithInputs:outputSets:lbInputSymbolId:lbOutputSymbolId:procedureIndex:signalEvents:transactionHandle:fwEnqueueDelay:memoryPoolId:), @[bufIn10], @[], @[@0], @[@0], @0, @[sigEvent], @0, @0, @0); if (chain10) { printf(" ChainingRequest with signalEvent: created\n"); BOOL valid10 = ((BOOL(*)(id,SEL))objc_msgSend)(chain10, @selector(validate)); printf(" validate: %s\n", valid10 ? "YES" : "NO"); } else { printf(" ChainingRequest with signalEvent: nil\n"); } } } @catch (NSException *ex) { printf(" Shared events EXCEPTION: %s\n", [[ex reason] UTF8String]); } } } } R.phase10_done = true; // Benchmark all eval paths side-by-side for final comparison printf("\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); printf(" EVAL PATH COMPARISON (side-by-side)\n"); printf("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); { int BENCH_ITERS = 200; for (int w = 0; w < 10; w++) { ((BOOL(*)(id,SEL,unsigned int,id,id,NSError**))objc_msgSend)( k1.model, @selector(evaluateWithQoS:options:request:error:), 21, @{}, req1, &e); } uint64_t ts = mach_absolute_time(); for (int i = 0; i < BENCH_ITERS; i++) { ((BOOL(*)(id,SEL,unsigned int,id,id,NSError**))objc_msgSend)( k1.model, @selector(evaluateWithQoS:options:request:error:), 21, @{}, req1, &e); } R.std_eval_ms = tb_ms(mach_absolute_time() - ts) / BENCH_ITERS; if (client) { for (int w = 0; w < 10; w++) { ((BOOL(*)(id,SEL,id,id,id,NSError**))objc_msgSend)( client, @selector(evaluateRealTimeWithModel:options:request:error:), k1.model, @{}, req1, &e); } ts = mach_absolute_time(); for (int i = 0; i < BENCH_ITERS; i++) { ((BOOL(*)(id,SEL,id,id,id,NSError**))objc_msgSend)( client, @selector(evaluateRealTimeWithModel:options:request:error:), k1.model, @{}, req1, &e); } R.rt_eval_ms = tb_ms(mach_absolute_time() - ts) / BENCH_ITERS; for (int w = 0; w < 10; w++) { ((BOOL(*)(id,SEL,id,id,id,unsigned int,NSError**))objc_msgSend)( client, @selector(doEvaluateDirectWithModel:options:request:qos:error:), k1.model, @{}, req1, 21, &e); } ts = mach_absolute_time(); for (int i = 0; i < BENCH_ITERS; i++) { ((BOOL(*)(id,SEL,id,id,id,unsigned int,NSError**))objc_msgSend)( client, @selector(doEvaluateDirectWithModel:options:request:qos:error:), k1.model, @{}, req1, 21, &e); } R.direct_eval_ms = tb_ms(mach_absolute_time() - ts) / BENCH_ITERS; } printf(" evaluateWithQoS (standard): %.3f ms/eval\n", R.std_eval_ms); printf(" evaluateRealTimeWithModel: %.3f ms/eval (%.2fx)\n", R.rt_eval_ms, R.std_eval_ms / R.rt_eval_ms); printf(" doEvaluateDirectWithModel: %.3f ms/eval (%.2fx)\n", R.direct_eval_ms, R.std_eval_ms / R.direct_eval_ms); if (R.process_request_works) { printf(" processRequest: %.3f ms/eval (%.2fx)\n", R.process_request_ms, R.std_eval_ms / R.process_request_ms); } } // ===================================================================== // PHASE 6: Summary // ===================================================================== printf("\n╔══════════════════════════════════════════════════════════╗\n"); printf("║ PHASE 6: Results Summary ║\n"); printf("╚══════════════════════════════════════════════════════════╝\n\n"); printf("┌──────────────────────────────────────────────────────────┐\n"); printf("│ Phase 1: Class Introspection │\n"); printf("│ Classes found: %d │\n", R.classes_found); printf("│ Classes missing: %d │\n", R.classes_missing); printf("├──────────────────────────────────────────────────────────┤\n"); printf("│ Phase 2: Symbol Discovery │\n"); printf("│ inputSymbolNames: %s │\n", R.has_input_symbols ? "YES" : "NO "); printf("│ outputSymbolNames: %s │\n", R.has_output_symbols ? "YES" : "NO "); printf("│ programHandle: %s │\n", R.has_program_handle ? "YES" : "NO "); printf("├──────────────────────────────────────────────────────────┤\n"); printf("│ Phase 3: IOSurface Mapping │\n"); printf("│ Mapper works: %s │\n", R.mapper_works ? "YES" : "NO "); printf("│ Buffer works: %s │\n", R.buffer_works ? "YES" : "NO "); printf("│ Got symbolIndex: %s │\n", R.got_symbol_index ? "YES" : "NO "); printf("├──────────────────────────────────────────────────────────┤\n"); printf("│ Phase 4: ChainingRequest │\n"); printf("│ validate passed: %s │\n", R.validate_passed ? "YES" : "NO "); printf("│ Chaining executed: %s │\n", R.chaining_executed ? "YES" : "NO "); printf("│ Sequential: %.3f ms/pair │\n", R.sequential_ms); if (R.chaining_executed) { printf("│ Chained: %.3f ms/pair │\n", R.chained_ms); printf("│ Speedup: %.2fx │\n", R.sequential_ms / R.chained_ms); } printf("├──────────────────────────────────────────────────────────┤\n"); printf("│ Phase 5: Alternative Paths │\n"); printf("│ RT eval works: %s │\n", R.realtime_eval_works ? "YES" : "NO "); printf("│ PerfStats works: %s │\n", R.perfstats_works ? "YES" : "NO "); if (R.perfstats_works) { printf("│ hwExecutionTime: %llu ns │\n", R.hw_exec_time_ns); } printf("├──────────────────────────────────────────────────────────┤\n"); printf("│ Phase 7: OutputSets with statsSurRef │\n"); printf("│ OutputSets works: %s │\n", R.outputsets_with_stats_works ? "YES" : "NO "); printf("│ Chaining works: %s │\n", R.chaining_with_stats_works ? "YES" : "NO "); printf("├──────────────────────────────────────────────────────────┤\n"); printf("│ Phase 8: Disk-based _ANEModel │\n"); printf("│ Model loads: %s │\n", R.disk_model_loads ? "YES" : "NO "); printf("│ Has symbols: %s │\n", R.disk_model_has_symbols ? "YES" : "NO "); printf("├──────────────────────────────────────────────────────────┤\n"); printf("│ Phase 9: processRequest │\n"); printf("│ Works: %s │\n", R.process_request_works ? "YES" : "NO "); if (R.process_request_works) { printf("│ Latency: %.3f ms/eval │\n", R.process_request_ms); } printf("├──────────────────────────────────────────────────────────┤\n"); printf("│ Phase 10: Shared Events │\n"); printf("│ Classes exist: %s │\n", R.shared_events_exist ? "YES" : "NO "); printf("├──────────────────────────────────────────────────────────┤\n"); printf("│ Eval Path Comparison (200 iters) │\n"); printf("│ Standard: %.3f ms/eval │\n", R.std_eval_ms); printf("│ RT: %.3f ms/eval (%.2fx) │\n", R.rt_eval_ms, R.std_eval_ms / (R.rt_eval_ms > 0 ? R.rt_eval_ms : 1)); printf("│ Direct: %.3f ms/eval (%.2fx) │\n", R.direct_eval_ms, R.std_eval_ms / (R.direct_eval_ms > 0 ? R.direct_eval_ms : 1)); if (R.process_request_works) { printf("│ ProcReq: %.3f ms/eval (%.2fx) │\n", R.process_request_ms, R.std_eval_ms / (R.process_request_ms > 0 ? R.process_request_ms : 1)); } printf("└──────────────────────────────────────────────────────────┘\n"); // Cleanup NSFileManager *fm = [NSFileManager defaultManager]; NSError *cleanupErr = nil; ((BOOL(*)(id,SEL,unsigned int,NSError**))objc_msgSend)(k1.model, @selector(unloadWithQoS:error:), 21, &cleanupErr); ((BOOL(*)(id,SEL,unsigned int,NSError**))objc_msgSend)(k2.model, @selector(unloadWithQoS:error:), 21, &cleanupErr); [fm removeItemAtPath:k1.tmpDir error:nil]; [fm removeItemAtPath:k2.tmpDir error:nil]; if (k1.ioIn) CFRelease(k1.ioIn); if (k1.ioOut) CFRelease(k1.ioOut); if (k2.ioIn) CFRelease(k2.ioIn); if (k2.ioOut) CFRelease(k2.ioOut); printf("\n=== ChainingRequest Deep Exploration v2 complete ===\n"); } return 0; }