ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Electron SharedTextureHandle:跨进程共享纹理的原生句柄结构与实战解析

Electron SharedTextureHandle:跨进程共享纹理的原生句柄结构与实战解析 Electron SharedTextureHandle跨进程共享纹理的原生句柄结构与实战解析【免费下载链接】electron:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS项目地址: https://gitcode.com/GitHub_Trending/el/electronSharedTextureHandle是 Electron 实验性sharedTextureAPI 中承载平台原生纹理句柄的核心数据结构用于把 Windows 的 NT HANDLE、macOS 的 IOSurface 或 Linux 的 dmabuf 平面描述导入 Electron 并转成 WebVideoFrame。本文基于 SharedTextureHandle 结构定义 展开结合 sharedTexture 模块文档、设计说明 与 源码实现系统讲解三大平台句柄字段的含义、生命周期约束与跨进程传输的完整流程帮助你在高性能渲染OSR 帧转发、视频合成、GPU 管线直连场景中安全地共享 GPU 纹理。一、SharedTextureHandle 在 sharedTexture API 中的定位Electron 的 sharedTexture 模块 提供三个托管 API 和一个底层入口sharedTexture.importSharedTexture(options)仅主进程把外部共享纹理导入为 SharedTextureImported 对象sharedTexture.sendSharedTexture(options, ...args)仅主进程把已导入的纹理转送到渲染进程带有 1000ms 超时sharedTexture.setSharedTextureReceiver(callback)仅渲染进程注册接收回调sharedTexture.subtle暴露 SharedTextureSubtle提供importSharedTexture、finishTransferSharedTexture等精细控制接口。导入纹理时传入的textureInfo是 SharedTextureImportTextureInfo 对象其中handle字段正是SharedTextureHandle——它按运行平台选择性地包含三类句柄字段之一。理解这个结构是正确使用整套 API 的前提。二、字段全解三大平台各自的句柄形态2.1 WindowsntHandleBuffer可选ntHandle Buffer (optional) _Windows_ NT HANDLE 持有共享纹理该句柄仅对当前进程有效。 rgba、bgra、rgbaf16 格式的纹理句柄不带 keyed mutex nv12 格式的纹理句柄带 keyed mutex。要点句柄是进程局部的local to current process。Windows 上通过CreateSharedHandle生成的 NT HANDLE 只对创建进程可见要交给其他进程必须用DuplicateHandle在远端进程中复制一份。因此调用importSharedTexture时必须保证该句柄已经存在于当前进程的句柄表中keyed mutex 与像素格式绑定rgba、bgra、rgbaf16三种 32bpp/浮点格式不带 keyed mutex而nv12格式Y 平面 2x2 交错 UV 平面的 12bpp 格式带 keyed mutex。keyed mutex 是 D3D11 共享纹理跨进程同步的标准机制原生侧代码在使用nv12纹理时必须先AcquireSync再释放所有权转移是破坏性的如 设计文档 所述Chromium 会接管GpuMemoryBuffer及其原生表示的所有权资源销毁时直接CloseHandle关闭句柄。对非 NT HANDLE旧式GetSharedHandle产物执行CloseHandle属于非法操作并会崩溃所以导入时只接受 NT HANDLE且 Electron 内部会先对句柄做一次Duplicate由 Chromium 持有副本的关闭权。2.2 macOSioSurfaceBuffer可选ioSurface Buffer (optional) _macOS_ IOSurfaceRef 持有共享纹理。注意该 IOSurface 是进程局部的非全局。传入的IOSurfaceRef是当前进程局部的不是设置kIOSurfaceIsGlobal的全局 surface该选项已废弃。要在进程间共享 IOSurface需要经mach_port传输复杂度远高于 Windows与 Windows 的“接管所有权”不同macOS 的IOSurface是引用计数资源。importSharedTexture不会夺取所有权而是让 Chromium 持有引用、递增引用计数因此源纹理可以在导入之后自行释放只要还有引用存在就不会被销毁设计文档指出Chromium 的 IPC 内部其实已经透明处理了 mach_port 的传递问题OSR 的paint事件能直接使用句柄即为此原因但 Electron 暴露的这条导入路径要求调用方自行保证句柄对目标进程可见。2.3 LinuxnativePixmap对象可选Linux 的句柄是一个结构体按平面plane描述共享纹理字段如下字段类型说明planesObject[]每个平面的描述数组一个纹理可有多个平面如 YUV 多平面格式planes[].stridenumber通过内存映射访问缓冲时使用的行距字节每个平面每条目一个planes[].offsetnumber通过内存映射访问缓冲时使用的偏移字节每个平面每条目一个planes[].sizenumber平面大小字节映射缓冲所必需planes[].fdnumber底层内存对象通常是 dmabuf的文件描述符modifierstring从 GBM 库获取的 modifier需传递给 EGL 驱动对应 Linux 的 Buffer Modifier 机制如 tiling 布局supportsZeroCopyWebGpuImportboolean是否支持零拷贝导入 WebGPU使用要点fd是进程级资源与ntHandle一样只对持有该描述符的进程有效。跨进程传递时必须让目标进程拿到该 fd如通过 socket 发送 SCM_RIGHTS再执行导入stride/offset/size与 dmabuf 导入约定一致原生侧EGL/GL导入eglGetNativeClientBufferANDROID或 Linux DMA-BUF 导入时依赖这些值计算每平面内存布局modifier是 GBM 布局修改符小端/大端、tile 布局编码导入 EGL 时缺失它可能导致驱动按线性布局误解显存supportsZeroCopyWebGpuImport为true时该纹理可零拷贝进入 WebGPU 管线避免 CPU-GPU 往返拷贝是做高性能转发时应优先检查的标志位。三、与 SharedTextureImportTextureInfo 配套使用SharedTextureHandle从不单独出现它总是 SharedTextureImportTextureInfo 的handle字段完整导入描述为const textureInfo { pixelFormat, // bgra | rgba | rgbaf16 | nv12 | nv16 | p010le colorSpace, // 可选ColorSpace 对象 codedSize, // { width, height }纹理完整尺寸 visibleRect, // 可选[0, 0, codedSize.width, codedSize.height] 内的可见子区域 timestamp, // 可选微秒时间戳会反映到 VideoFrame handle: { // SharedTextureHandle按平台取其一 ntHandle, // Windows ioSurface, // macOS nativePixmap // Linux } }支持的pixelFormat及其平面结构pixelFormat说明bgra32bpp BGRA字节序1 平面rgba32bpp RGBA字节序1 平面rgbaf16半浮点 RGBA1 平面nv1212bppY 平面 2x2 交错 UV 平面Windows 下带 keyed mutexnv1616bppY 平面 2x1 交错 UV 平面p010le4:2:0 10-bit YUV小端注意timestamp以微秒为单位会直接写入生成的VideoFrame在视频解码/合成场景中用于保持时间戳连续。四、跨进程传输的源码级实现4.1 主进程侧引用计数与 1000ms 超时lib/browser/api/shared-texture.ts 是托管 API 的实现。importSharedTexture为每个导入对象生成textureIdrandomUUID()并注册进managedSharedTexturesMap记录主进程引用mainReference与每个渲染帧的引用rendererFrameReferencessendSharedTexture 内部先调用imported.subtle.startTransferSharedTexture()创建可序列化的 SharedTextureTransfer 对象再通过ipcMainInternalUtils.invokeInWebFrameMain以 IPC_MESSAGES.IMPORT_SHARED_TEXTURE_TRANSFER_MAIN_TO_RENDERER 消息投递到目标帧实现里Promise.race了一个 1000ms 超时transferTimeout超时即抛出transfer shared texture timed out ... ensure you have registered receiver at renderer process——这正是文档中“必须先注册接收者”的硬性约束来源渲染进程回传一个 SharedTextureSyncToken 后主进程调用imported.subtle.setReleaseSyncToken(syncToken)把释放时机绑定到该 SyncToken 在 GPU 进程被信号化之后防止 GPU 还在用该纹理时主进程先行销毁资源release 的引用计数逻辑只有当mainReference与所有rendererFrameReferences都清零后才调用底层texture.subtle.release(callback)并在回调里触发用户传入的allReferencesReleased。这就是文档中“所有进程都释放引用前应保持纹理有效”的机制落地。4.2 底层原理SharedImage Mailbox SyncTokenshell/common/api/shared_texture/README.md 解释了为什么选择 Chromium 的SharedImage作为外部纹理的载体SharedImageInterface::CreateSharedImage接受携带原生句柄的GpuMemoryBufferHandle即 Windows NT HANDLE、macOS IOSurfaceRef、Linux 每平面 fd 的NativePixmapHandle正好对应SharedTextureHandle的三个平台字段。跨进程共享的关键在于SharedImage持有指向 GPU 进程中SharedImageBacking的Mailbox引用通过SharedImageInterface-ImportSharedImage与ClientSharedImage-Export序列化出足够的信息另一进程即可重新取回同一个SharedImage且可复用 mojo 序列化器以字符串形式传输。帧生命周期则由SyncToken保证当同一个 Mailbox 在两个进程各有SharedImage实例时销毁必须等待 GPU 完成使用——例如在渲染进程用VideoFrame进入 WebGPU 管线后销毁令牌由 WebGPU 生成渲染结束前资源不会被销毁。SharedTextureImportedSubtle.release的可选 callback 以及getFrameCreationSyncToken/setReleaseSyncToken等 SharedTextureImportedSubtle 接口都是围绕这条同步链暴露的精细控制点。五、实战从 OSR paint 事件到渲染进程绘制Electron 自带的标准用法是以离屏渲染OSR作为共享纹理的输入源设置 webPreferences.offscreen.useSharedTexture 为true后WebContents 的paint事件 会携带textureOffscreenSharedTexture其中的textureInfo就是一个可直接喂给importSharedTexture的SharedTextureImportTextureInfo含平台handle。完整闭环可见 官方测试用例注意该测试目前仅在 macOS arm64 上运行// spec/api-shared-texture-spec.ts 中托管 API 的核心步骤 const osr new BrowserWindow({ width: 128, height: 128, webPreferences: { offscreen: { useSharedTexture: true } } }); osr.webContents.setFrameRate(1); osr.webContents.on(paint, async (event) { const texture event.texture; if (!texture) return; // GPU 不可用时跳过 // Step 2: 导入textureInfo.handle 即 SharedTextureHandle const imported sharedTexture.importSharedTexture({ textureInfo: texture.textureInfo, allReferencesReleased: () { // 所有进程引用释放后才释放 OSR 源纹理 texture.release(); } }); // Step 3: 发送到渲染进程渲染进程需先 setSharedTextureReceiver await sharedTexture.sendSharedTexture({ frame: win.webContents.mainFrame, // 子帧需启用 nodeIntegrationInSubFrames importedSharedTexture: imported }); // Step 4: 主进程侧立即释放自己的引用 imported.release(); });配套 fixture 展示了渲染进程的接收与 WebGPU 渲染细节managed/preload.js 通过sharedTexture.setSharedTextureReceiver接收importedSharedTexture并附加...argsmanaged/renderer.js 将getVideoFrame()得到的VideoFrame导入 WebGPU 纹理并绘制最后用 canvas 逐像素比对截图允许 1% 色差验证正确性subtle 目录 则演示了不经托管 API、直接用subtle.importSharedTexturestartTransferSharedTexturerelease(callback)手动管理生命周期的路径。六、使用约束与常见问题句柄必须对目标进程可见ntHandle/ioSurface/nativePixmap.fd都是进程局部资源调用importSharedTexture的进程必须已持有有效句柄跨进程请先完成句柄复制DuplicateHandle、mach_port、fd 传递再导入。Windows 只接受 NT HANDLE非 NT HANDLE 会在 Chromium 销毁资源时被CloseHandle导致崩溃导入时 Electron 会先Duplicate一份交给底层。及时release共享纹理池容量有限OSR 场景下尤其如此文档明确要求“尽快释放”托管 API 下release()只是减引用真正销毁发生在最后一个引用释放且 GPU 完成使用之后。1000ms 传输超时调用sendSharedTexture前必须确认渲染进程存活且已注册接收者否则 Promise 会以超时错误拒绝目标为非主帧时需开启webPreferences.nodeIntegrationInSubFrames。实验性 APIsharedTexture全部方法标注Experimental可能在后续版本移除设计文档也提醒 Chromium 的SharedImage接口尤其GpuMemoryBuffer/VideoFrame生命周期管理迭代较快行为以当前仓库版本为准。七、小结SharedTextureHandle虽然只是三个平台字段的薄封装但它决定了外部纹理能否被 Electron 正确接管Windows 侧要区分 NT HANDLE 与 keyed mutex 规则macOS 侧要理解 IOSurface 引用计数语义Linux 侧要完整描述 dmabuf 平面布局与 modifier。配合 SharedTextureImportTextureInfo 的像素格式描述、sharedTexture模块的导入/转送/接收三件套以及底层SharedImageSyncToken的 GPU 同步机制这条链路可以支撑从 OSR 帧零拷贝转发到渲染进程 WebGPU 渲染的高性能场景。深入阅读 设计文档、主进程实现 与 回归测试是掌握该特性的最短路径。【免费下载链接】electron:electron: Build cross-platform desktop apps with JavaScript, HTML, and CSS项目地址: https://gitcode.com/GitHub_Trending/el/electron创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表