Something went wrong. Try again.
Native control, inspection, UI automation and evidence capture for a running Witcher 3 process.
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126// Host-side vkQueuePresentKHR cadence. No JSON, file writes or allocation per sample.#include <vulkan/vulkan.h>#include <vulkan/vk_layer.h>#include <atomic>#include <cstring>#include <cstdio>#include <cstdlib>#include <mutex>#include <fcntl.h>#include <unistd.h>#include <sys/mman.h>#include <sys/syscall.h>#include <time.h>
static constexpr uint64_t MAGIC = 0x31544e4553455250ULL;static constexpr size_t CAP = 65536;struct Header { uint64_t magic, version, pid, capacity, record_size; uint64_t enabled, count, dropped, deadline_ns, epoch, in_flight, presents; uint64_t reserved[4];};struct Record { uint64_t sequence, begin_ns, end_ns, swapchain, thread_id, epoch; int32_t result; uint32_t swapchain_count; uint64_t observer_ns; };static_assert(sizeof(Header)==128 && sizeof(Record)==64);static Header* shared = nullptr;static std::once_flag init_once;static std::atomic_flag writer = ATOMIC_FLAG_INIT;static uint64_t now_ns() { timespec t{}; clock_gettime(CLOCK_MONOTONIC,&t); return uint64_t(t.tv_sec)*1000000000+t.tv_nsec; }static uint64_t get(uint64_t* p) { return __atomic_load_n(p,__ATOMIC_ACQUIRE); }static void put(uint64_t* p,uint64_t v) { __atomic_store_n(p,v,__ATOMIC_RELEASE); }static void init_buffer() { const char* dir=getenv("PATHDEVKIT_PRESENT_DIR"); if(!dir) return; char cmd[4096]{}; int c=open("/proc/self/cmdline",O_RDONLY); if(c<0)return; read(c,cmd,sizeof(cmd)-1);close(c); if(!strstr(cmd,"witcher3.exe"))return; char path[4096];snprintf(path,sizeof(path),"%s/%d.bin",dir,getpid()); int fd=open(path,O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW,0600);if(fd<0)return; size_t size=sizeof(Header)+CAP*sizeof(Record); if(ftruncate(fd,size)!=0){close(fd);return;} void* mem=mmap(nullptr,size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);close(fd); if(mem==MAP_FAILED)return; // Fault pages once before capture. Render callback only accesses bounded memory. memset(mem,0,size);shared=(Header*)mem; shared->version=1;shared->pid=getpid();shared->capacity=CAP;shared->record_size=sizeof(Record); put(&shared->magic,MAGIC);}static void* key(void* h){return h?*(void**)h:nullptr;}struct Instance { void* key=nullptr; VkInstance handle{}; PFN_vkGetInstanceProcAddr gipa{}; PFN_GetPhysicalDeviceProcAddr phys{}; PFN_vkDestroyInstance destroy{}; };struct Device { void* key=nullptr; VkDevice handle{}; PFN_vkGetDeviceProcAddr gdpa{}; PFN_vkQueuePresentKHR present{}; PFN_vkDestroyDevice destroy{}; };static Instance instances[16];static Device devices[16];static std::mutex objects;static Instance* instance(void* k){if(!k)return nullptr;for(auto& x:instances)if(__atomic_load_n(&x.key,__ATOMIC_ACQUIRE)==k)return &x;return nullptr;}static Device* device(void* k){if(!k)return nullptr;for(auto& x:devices)if(__atomic_load_n(&x.key,__ATOMIC_ACQUIRE)==k)return &x;return nullptr;}extern "C" {VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance,const char*);VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice,const char*);VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCreateInfo* info,const VkAllocationCallbacks* alloc,VkInstance* out){ auto chain=(VkLayerInstanceCreateInfo*)info->pNext; while(chain && (chain->sType!=VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO || chain->function!=VK_LAYER_LINK_INFO))chain=(VkLayerInstanceCreateInfo*)chain->pNext; if(!chain)return VK_ERROR_INITIALIZATION_FAILED; auto link=chain->u.pLayerInfo;auto gipa=link->pfnNextGetInstanceProcAddr;auto phys=link->pfnNextGetPhysicalDeviceProcAddr; chain->u.pLayerInfo=link->pNext; auto create=(PFN_vkCreateInstance)gipa(nullptr,"vkCreateInstance"); VkResult r=create(info,alloc,out);if(r!=VK_SUCCESS)return r; std::lock_guard<std::mutex> guard(objects); for(auto& x:instances)if(!x.key){x.handle=*out;x.gipa=gipa;x.phys=phys;x.destroy=(PFN_vkDestroyInstance)gipa(*out,"vkDestroyInstance");__atomic_store_n(&x.key,key(*out),__ATOMIC_RELEASE);return r;} ((PFN_vkDestroyInstance)gipa(*out,"vkDestroyInstance"))(*out,alloc);return VK_ERROR_TOO_MANY_OBJECTS;}VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance h,const VkAllocationCallbacks* a){ auto x=instance(key(h));if(!x)return;auto fn=x->destroy;fn(h,a);std::lock_guard<std::mutex> g(objects);__atomic_store_n(&x->key,(void*)nullptr,__ATOMIC_RELEASE);}VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice physical,const VkDeviceCreateInfo* info,const VkAllocationCallbacks* alloc,VkDevice* out){ auto chain=(VkLayerDeviceCreateInfo*)info->pNext; while(chain && (chain->sType!=VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO || chain->function!=VK_LAYER_LINK_INFO))chain=(VkLayerDeviceCreateInfo*)chain->pNext; if(!chain)return VK_ERROR_INITIALIZATION_FAILED; auto link=chain->u.pLayerInfo;auto gipa=link->pfnNextGetInstanceProcAddr;auto gdpa=link->pfnNextGetDeviceProcAddr; auto inst=instance(key(physical));if(!inst)return VK_ERROR_INITIALIZATION_FAILED; auto create=(PFN_vkCreateDevice)gipa(inst->handle,"vkCreateDevice");chain->u.pLayerInfo=link->pNext; VkResult r=create(physical,info,alloc,out);if(r!=VK_SUCCESS)return r; std::lock_guard<std::mutex> g(objects); for(auto& x:devices)if(!x.key){x.handle=*out;x.gdpa=gdpa;x.present=(PFN_vkQueuePresentKHR)gdpa(*out,"vkQueuePresentKHR");x.destroy=(PFN_vkDestroyDevice)gdpa(*out,"vkDestroyDevice");__atomic_store_n(&x.key,key(*out),__ATOMIC_RELEASE);return r;} ((PFN_vkDestroyDevice)gdpa(*out,"vkDestroyDevice"))(*out,alloc);return VK_ERROR_TOO_MANY_OBJECTS;}VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(VkDevice h,const VkAllocationCallbacks* a){ auto x=device(key(h));if(!x)return;auto fn=x->destroy;fn(h,a);std::lock_guard<std::mutex> g(objects);__atomic_store_n(&x->key,(void*)nullptr,__ATOMIC_RELEASE);}VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR(VkQueue queue,const VkPresentInfoKHR* info){ auto d=device(key(queue));if(!d || !d->present)return VK_ERROR_INITIALIZATION_FAILED; std::call_once(init_once,init_buffer); if(!shared)return d->present(queue,info); __atomic_fetch_add(&shared->presents,1,__ATOMIC_RELAXED); if(!get(&shared->enabled))return d->present(queue,info); if(writer.test_and_set(std::memory_order_acquire)){ __atomic_fetch_add(&shared->dropped,1,__ATOMIC_RELAXED);return d->present(queue,info); } put(&shared->in_flight,1); // Recheck after publication so stop/reset cannot race an old enabled read. uint64_t begin=now_ns(); if(!get(&shared->enabled) || begin>=get(&shared->deadline_ns)){ put(&shared->enabled,0);put(&shared->in_flight,0);writer.clear(std::memory_order_release);return d->present(queue,info); } uint64_t index=get(&shared->count),epoch=get(&shared->epoch); if(index>=CAP){__atomic_fetch_add(&shared->dropped,1,__ATOMIC_RELAXED);put(&shared->enabled,0);put(&shared->in_flight,0);writer.clear(std::memory_order_release);return d->present(queue,info);} uint64_t pre=now_ns();VkResult result=d->present(queue,info);uint64_t end=now_ns(); auto records=(Record*)(shared+1);auto& r=records[index]; r={index,begin,end,info->swapchainCount?(uint64_t)info->pSwapchains[0]:0,(uint64_t)syscall(SYS_gettid),epoch,(int32_t)result,info->swapchainCount,pre-begin}; r.observer_ns+=now_ns()-end; put(&shared->count,index+1);put(&shared->in_flight,0);writer.clear(std::memory_order_release);return result;}VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice h,const char* name){ if(!strcmp(name,"vkGetDeviceProcAddr"))return (PFN_vkVoidFunction)vkGetDeviceProcAddr; if(!strcmp(name,"vkQueuePresentKHR"))return (PFN_vkVoidFunction)vkQueuePresentKHR; if(!strcmp(name,"vkDestroyDevice"))return (PFN_vkVoidFunction)vkDestroyDevice; auto d=device(key(h));return d?d->gdpa(h,name):nullptr;}VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance h,const char* name){ #define FN(n) if(!strcmp(name,#n))return (PFN_vkVoidFunction)n; FN(vkGetInstanceProcAddr) FN(vkGetDeviceProcAddr) FN(vkCreateInstance) FN(vkDestroyInstance) FN(vkCreateDevice) FN(vkDestroyDevice) FN(vkQueuePresentKHR) #undef FN auto i=instance(key(h));return i?i->gipa(h,name):nullptr;}VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL physical_proc(VkInstance h,const char* name){auto i=instance(key(h));return i?(i->phys?i->phys(h,name):i->gipa(h,name)):nullptr;}VKAPI_ATTR VkResult VKAPI_CALL vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface* info){ if(info->loaderLayerInterfaceVersion<2)return VK_ERROR_INITIALIZATION_FAILED; info->loaderLayerInterfaceVersion=2;info->pfnGetInstanceProcAddr=vkGetInstanceProcAddr;info->pfnGetDeviceProcAddr=vkGetDeviceProcAddr;info->pfnGetPhysicalDeviceProcAddr=physical_proc;return VK_SUCCESS;}}