.版本 2 .支持库 spec .程序集 窗口程序集_启动窗口, , , 开源作者:z573277679 .程序集变量 集_D3D设备, 整数型 .程序集变量 集_D3D上下文, 整数型 .程序集变量 集_DXGI副本, 整数型 .程序集变量 集_全屏宽, 整数型 .程序集变量 集_全屏高, 整数型 .程序集变量 集_已初始化, 逻辑型 .程序集变量 集_RawBuffer, 字节集 .程序集变量 集_RawPitch, 整数型 .子程序 DXGI_截图, 字节集, 公开, 开源作者:z573277679 .参数 窗口句柄, 整数型, 可空 .参数 区域_左, 整数型, 可空 .参数 区域_顶, 整数型, 可空 .参数 区域_宽, 整数型, 可空 .参数 区域_高, 整数型, 可空 .局部变量 帧信息, 字节集 .局部变量 桌面资源, 整数型 .局部变量 纹理接口, 整数型 .局部变量 内存纹理, 整数型 .局部变量 映射指针, 整数型 .局部变量 结果, 整数型 .局部变量 描述, 字节集 .局部变量 显存行距, 整数型 .局部变量 结果位图, 字节集 .局部变量 源指针, 整数型 .局部变量 目标指针, 整数型 .局部变量 行字节数, 整数型 .局部变量 GUID, 字节集 .局部变量 截取X, 整数型 .局部变量 截取Y, 整数型 .局部变量 截取W, 整数型 .局部变量 截取H, 整数型 .局部变量 临时矩形, 整数型, , "4" .局部变量 像素数据大小, 整数型 .局部变量 总内存大小, 整数型 .局部变量 HasNewFrame, 逻辑型 .局部变量 CurrentSourcePtr, 整数型 .局部变量 CurrentSourcePitch, 整数型 .局部变量 映射缓冲, 字节集 ' 1. 自动初始化 .如果真 (集_已初始化 = 假) .如果真 (内部_初始化 () = 假) 返回 ({ }) .如果真结束 .如果真结束 ' ============================================================ ' 第一阶段:尝试从 GPU 获取最新帧 ' ============================================================ HasNewFrame = 假 帧信息 = 取空白字节集 (48) ' 参数3(超时)设为0,表示立即返回,不阻塞线程 ' 利用 Asm_微秒延时 在外部控制节奏,防止驱动层死等导致 UI 锁死 结果 = COM_3 (集_DXGI副本, 8, 0, 取字节集指针 (帧信息), 取整数指针 (桌面资源)) .如果 (结果 ≥ 0) HasNewFrame = 真 .否则 ' --- 微秒延时逻辑引入 --- ' 结果 = -2005270489 代表 DXGI_ERROR_WAIT_TIMEOUT (屏幕画面无更新) .如果 (结果 = -2005270489) ' 此时屏幕没动,我们执行 500 微秒的极速避让,降低 CPU 消耗 Asm_微秒延时 (500) ' 检查缓存:如果有旧数据,我们直接跳转到生成阶段,实现“视觉满帧” .如果真 (取字节集长度 (集_RawBuffer) = 0) 返回 ({ }) .如果真结束 .否则 ' 设备丢失处理 (DXGI_ERROR_DEVICE_REMOVED 等) .如果真 (结果 = -2005270523 或 结果 = -2005270490) 集_已初始化 = 假 .如果真结束 返回 ({ }) .如果结束 .如果结束 ' ============================================================ ' 第二阶段:如果有新帧,更新全局缓存 ' ============================================================ .如果真 (HasNewFrame) ' --- 获取纹理信息 --- GUID = { 242, 170, 21, 111, 8, 210, 137, 78, 154, 180, 72, 149, 53, 211, 79, 156 } COM_2 (桌面资源, 0, 取字节集指针 (GUID), 取整数指针 (纹理接口)) 描述 = 取空白字节集 (44) COM_1 (纹理接口, 10, 取字节集指针 (描述)) 集_全屏宽 = 取字节集数据 (描述, #整数型, 1) 集_全屏高 = 取字节集数据 (描述, #整数型, 5) ' --- 创建 Staging Texture (用于显存回读内存) --- 写到内存 (3, 取字节集指针 (描述) + 28, 4) ' CPU Access Read 写到内存 (0, 取字节集指针 (描述) + 32, 4) 写到内存 (131072, 取字节集指针 (描述) + 36, 4) ' D3D11_USAGE_STAGING 写到内存 (0, 取字节集指针 (描述) + 40, 4) COM_3 (集_D3D设备, 5, 取字节集指针 (描述), 0, 取整数指针 (内存纹理)) COM_2 (集_D3D上下文, 47, 内存纹理, 纹理接口) ' CopyResource ' --- Map 映射 --- 映射缓冲 = 取空白字节集 (16) 映射指针 = 取字节集指针 (映射缓冲) 结果 = COM_5 (集_D3D上下文, 14, 内存纹理, 0, 1, 0, 映射指针) .如果真 (结果 ≥ 0) 源指针 = _内存_读整数 (映射指针) 显存行距 = _内存_读整数 (映射指针 + 4) .如果真 (源指针 ≠ 0) 集_RawPitch = 显存行距 总内存大小 = 显存行距 × 集_全屏高 .如果真 (取字节集长度 (集_RawBuffer) ≠ 总内存大小) 集_RawBuffer = 取空白字节集 (总内存大小) .如果真结束 ' 汇编搬运 _内存_复制 (取字节集指针 (集_RawBuffer), 源指针, 总内存大小) .如果真结束 COM_2 (集_D3D上下文, 15, 内存纹理, 0) ' Unmap .如果真结束 ' 释放 GPU 资源 COM_释放 (内存纹理) COM_释放 (纹理接口) COM_释放 (桌面资源) COM_0 (集_DXGI副本, 14) ' ReleaseFrame .如果真结束 ' ============================================================ ' 第三阶段:数据准备 (CurrentSourcePtr 始终指向最新有效的缓存) ' ============================================================ CurrentSourcePtr = 取字节集指针 (集_RawBuffer) CurrentSourcePitch = 集_RawPitch ' ============================================================ ' 第四阶段:区域计算(裁剪逻辑) ' ============================================================ .如果 (窗口句柄 ≠ 0) 结果 = DwmGetWindowAttribute (窗口句柄, 9, 取整数指针 (临时矩形 [1]), 16) .如果真 (结果 ≠ 0 或 临时矩形 [3] - 临时矩形 [1] ≤ 0) GetWindowRect (窗口句柄, 取整数指针 (临时矩形 [1])) .如果真结束 截取X = 临时矩形 [1] 截取Y = 临时矩形 [2] 截取W = 临时矩形 [3] - 临时矩形 [1] 截取H = 临时矩形 [4] - 临时矩形 [2] .否则 .如果 (区域_宽 > 0 且 区域_高 > 0) 截取X = 区域_左 截取Y = 区域_顶 截取W = 区域_宽 截取H = 区域_高 .否则 截取X = 0 截取Y = 0 截取W = 集_全屏宽 截取H = 集_全屏高 .如果结束 .如果结束 ' 边界修正 .如果真 (截取X < 0) 截取W = 截取W + 截取X 截取X = 0 .如果真结束 .如果真 (截取Y < 0) 截取H = 截取H + 截取Y 截取Y = 0 .如果真结束 .如果真 (截取X + 截取W > 集_全屏宽) 截取W = 集_全屏宽 - 截取X .如果真结束 .如果真 (截取Y + 截取H > 集_全屏高) 截取H = 集_全屏高 - 截取Y .如果真结束 .如果真 (截取W ≤ 0 或 截取H ≤ 0) 返回 ({ }) .如果真结束 ' ============================================================ ' 第五阶段:汇编级 BMP 封装 ' ============================================================ 行字节数 = 截取W × 4 像素数据大小 = 行字节数 × 截取H 总内存大小 = 54 + 像素数据大小 结果位图 = 取空白字节集 (总内存大小) 目标指针 = 取字节集指针 (结果位图) ASM_写BMP头 (目标指针, 截取W, 截取H, 像素数据大小) CurrentSourcePtr = CurrentSourcePtr + 截取Y × CurrentSourcePitch + 截取X × 4 ASM_复制并翻转 (CurrentSourcePtr, 目标指针 + 54, 行字节数, 截取H, CurrentSourcePitch) 返回 (结果位图) .子程序 DXGI_清理, , 公开, 显式清理资源 开源作者:z573277679 COM_释放 (集_DXGI副本) COM_释放 (集_D3D上下文) COM_释放 (集_D3D设备) 集_已初始化 = 假 .子程序 内部_初始化, 逻辑型, , 开源作者:z573277679 .局部变量 工厂, 整数型 .局部变量 显卡, 整数型 .局部变量 输出, 整数型 .局部变量 输出1, 整数型 .局部变量 结果, 整数型 .局部变量 GUID, 字节集 ' 1. 防止重复初始化 COM_释放 (集_DXGI副本) COM_释放 (集_D3D上下文) COM_释放 (集_D3D设备) ' 2. 创建 D3D 设备 结果 = D3D11CreateDevice (0, 1, 0, 1, 0, 0, 7, 集_D3D设备, 0, 集_D3D上下文) .如果真 (结果 < 0) 返回 (假) .如果真结束 ' 3. 创建 DXGI GUID = { 120, 174, 10, 119, 111, 242, 186, 77, 168, 41, 37, 60, 131, 209, 179, 135 } CreateDXGIFactory1 (取字节集指针 (GUID), 工厂) COM_2 (工厂, 12, 0, 取整数指针 (显卡)) COM_2 (显卡, 7, 0, 取整数指针 (输出)) GUID = { 168, 222, 205, 0, 155, 147, 131, 75, 163, 64, 166, 133, 34, 102, 102, 204 } COM_2 (输出, 0, 取字节集指针 (GUID), 取整数指针 (输出1)) 结果 = COM_2 (输出1, 22, 集_D3D设备, 取整数指针 (集_DXGI副本)) COM_释放 (输出1) COM_释放 (输出) COM_释放 (显卡) COM_释放 (工厂) 集_已初始化 = 结果 ≥ 0 ' 预热逻辑,打通数据管道 .如果真 (集_已初始化) 内部_预热 () .如果真结束 返回 (集_已初始化) .子程序 内部_预热, , , 开源作者:z573277679 .局部变量 帧信息, 字节集 .局部变量 资源, 整数型 .局部变量 i, 整数型 .局部变量 结果, 整数型 帧信息 = 取空白字节集 (48) .计次循环首 (3, i) 资源 = 0 结果 = COM_3 (集_DXGI副本, 8, 50, 取字节集指针 (帧信息), 取整数指针 (资源)) .如果真 (结果 ≥ 0) COM_释放 (资源) COM_0 (集_DXGI副本, 14) 跳出循环 () .如果真结束 .如果真 (结果 = -2005270489) 延迟 (10) .如果真结束 .计次循环尾 () .子程序 _内存_读整数, 整数型, 公开, 读取地址处的整数 开源作者:z573277679 .参数 内存地址, 整数型 置入代码 ({ 139, 69, 8, 139, 0, 201, 194, 4, 0 }) 返回 (0) .子程序 _内存_复制, , 公开, 将一块内存区域的数据复制到另一块内存区域 开源作者:z573277679 .参数 目标地址, 整数型, , 数据要复制到的目标内存地址 .参数 源地址, 整数型, , 要复制的数据源内存地址 .参数 复制长度, 整数型, , 要复制的数据字节数 置入代码 ({ 86, 87, 81, 139, 125, 8, 139, 117, 12, 139, 77, 16, 252, 193, 233, 2, 243, 165, 139, 77, 16, 131, 225, 3, 243, 164, 89, 95, 94, 201, 194, 12, 0 }) .子程序 _内存_填充, , 公开, 开源作者:z573277679 .参数 目标地址, 整数型 .参数 填充值, 字节型, , 0-255 .参数 填充长度, 整数型 置入代码 ({ 252, 139, 125, 8, 15, 182, 69, 12, 136, 196, 102, 137, 193, 193, 224, 16, 102, 137, 200, 139, 77, 16, 137, 202, 193, 233, 2, 243, 171, 137, 209, 131, 225, 3, 243, 170, 201, 194, 12, 0 }) .子程序 ASM_复制并翻转, , 公开, BMP翻转复制 开源作者:z573277679 .参数 源地址, 整数型 .参数 目标地址, 整数型 .参数 宽度字节, 整数型 .参数 高度, 整数型 .参数 源行距, 整数型 置入代码 ({ 83, 86, 87, 139, 117, 8, 139, 125, 12, 139, 77, 16, 139, 85, 20, 139, 93, 24, 137, 208, 72, 15, 175, 193, 1, 199, 86, 87, 81, 131, 249, 16, 124, 17, 15, 16, 6, 15, 17, 7, 131, 198, 16, 131, 199, 16, 131, 233, 16, 235, 234, 131, 249, 0, 116, 9, 138, 6, 136, 7, 70, 71, 73, 235, 242, 89, 95, 94, 1, 222, 41, 207, 74, 117, 207, 95, 94, 91, 201, 194, 20, 0 }) .子程序 ASM_写BMP头, , 公开, 直接写入BMP头 开源作者:z573277679 .参数 目标指针, 整数型 .参数 宽, 整数型 .参数 高, 整数型 .参数 数据大小, 整数型 置入代码 ({ 139, 125, 8, 139, 77, 12, 139, 85, 16, 139, 69, 20, 102, 199, 7, 66, 77, 141, 112, 54, 137, 119, 2, 199, 71, 6, 0, 0, 0, 0, 199, 71, 10, 54, 0, 0, 0, 199, 71, 14, 40, 0, 0, 0, 137, 79, 18, 137, 87, 22, 199, 71, 26, 1, 0, 32, 0, 199, 71, 30, 0, 0, 0, 0, 137, 71, 34, 49, 192, 137, 71, 38, 137, 71, 42, 137, 71, 46, 137, 71, 50, 201, 194, 16, 0 }) .子程序 Asm_微秒延时, , 公开, 基于RDTSC的CPU忙等待,建议值 100-500us 开源作者:z573277679 .参数 参_微秒, 整数型 置入代码 ({ 139, 77, 8, 133, 201, 116, 28, 105, 201, 184, 11, 0, 0, 15, 49, 137, 195, 137, 214, 243, 144, 15, 49, 41, 216, 25, 242, 133, 210, 117, 4, 57, 200, 114, 240 }) .子程序 取字节集指针, 整数型, 公开, 开源作者:z573277679 .参数 字节集数据, 字节集, 参考 置入代码 ({ 139, 69, 8, 139, 0, 133, 192, 116, 3, 131, 192, 8, 201, 194, 4, 0 }) 返回 (0) .子程序 取整数指针, 整数型, 公开, 开源作者:z573277679 .参数 整数, 整数型, 参考 置入代码 ({ 139, 69, 8, 201, 194, 4, 0 }) 返回 (0) .子程序 COM_释放, 整数型, , 开源作者:z573277679 .参数 ptr, 整数型 .如果真 (ptr ≠ 0) 返回 (COM_0 (ptr, 2)) .如果真结束 返回 (0) .子程序 COM_0, 整数型, , 开源作者:z573277679 .参数 i, 整数型 .参数 idx, 整数型 置入代码 ({ 139, 69, 8, 80, 139, 0, 139, 77, 12, 193, 225, 2, 1, 200, 139, 0, 255, 208, 201, 194, 8, 0 }) 返回 (0) .子程序 COM_1, 整数型, , 开源作者:z573277679 .参数 i, 整数型 .参数 idx, 整数型 .参数 p1, 整数型 置入代码 ({ 139, 69, 16, 80, 139, 69, 8, 80, 139, 0, 139, 77, 12, 193, 225, 2, 1, 200, 139, 0, 255, 208, 201, 194, 12, 0 }) 返回 (0) .子程序 COM_2, 整数型, , 开源作者:z573277679 .参数 i, 整数型 .参数 idx, 整数型 .参数 p1, 整数型 .参数 p2, 整数型 置入代码 ({ 139, 69, 20, 80, 139, 69, 16, 80, 139, 69, 8, 80, 139, 0, 139, 77, 12, 193, 225, 2, 1, 200, 139, 0, 255, 208, 201, 194, 16, 0 }) 返回 (0) .子程序 COM_3, 整数型, , 开源作者:z573277679 .参数 i, 整数型 .参数 idx, 整数型 .参数 p1, 整数型 .参数 p2, 整数型 .参数 p3, 整数型 置入代码 ({ 139, 69, 24, 80, 139, 69, 20, 80, 139, 69, 16, 80, 139, 69, 8, 80, 139, 0, 139, 77, 12, 193, 225, 2, 1, 200, 139, 0, 255, 208, 201, 194, 20, 0 }) 返回 (0) .子程序 COM_5, 整数型, , 开源作者:z573277679 .参数 i, 整数型 .参数 idx, 整数型 .参数 p1, 整数型 .参数 p2, 整数型 .参数 p3, 整数型 .参数 p4, 整数型 .参数 p5, 整数型 置入代码 ({ 139, 69, 32, 80, 139, 69, 28, 80, 139, 69, 24, 80, 139, 69, 20, 80, 139, 69, 16, 80, 139, 69, 8, 80, 139, 0, 139, 77, 12, 193, 225, 2, 1, 200, 139, 0, 255, 208, 201, 194, 28, 0 }) 返回 (0) .子程序 _按钮1_被单击, , , 开源作者:z573277679 .局部变量 图片, 字节集 .局部变量 耗时, 整数型 .局部变量 句柄, 整数型 调试输出 (“---------------- [开始功能测试] ----------------”) ' 1. 全屏 耗时 = 取启动时间 () 图片 = DXGI_截图 () 耗时 = 取启动时间 () - 耗时 .如果真 (取字节集长度 (图片) > 0) 调试输出 (“[全屏截图] 成功 | 大小: ” + 到文本 (取字节集长度 (图片)) + “ 字节 | 耗时: ” + 到文本 (耗时) + “ms”) 写到文件 (取运行目录 () + “\测试_全屏.bmp”, 图片) .如果真结束 ' 2. 窗口 句柄 = 取窗口句柄 () 耗时 = 取启动时间 () 图片 = DXGI_截图 (句柄) 耗时 = 取启动时间 () - 耗时 .如果真 (取字节集长度 (图片) > 0) 调试输出 (“[窗口截图] 成功 | 句柄: ” + 到文本 (句柄) + “ | 耗时: ” + 到文本 (耗时) + “ms”) 写到文件 (取运行目录 () + “\测试_窗口.bmp”, 图片) .如果真结束 ' 3. 区域 耗时 = 取启动时间 () 图片 = DXGI_截图 (0, 0, 0, 500, 500) 耗时 = 取启动时间 () - 耗时 .如果真 (取字节集长度 (图片) > 0) 调试输出 (“[区域截图] 成功 | 500x500 | 耗时: ” + 到文本 (耗时) + “ms”) 写到文件 (取运行目录 () + “\测试_区域.bmp”, 图片) .如果真结束 调试输出 (“---------------- [测试结束] ----------------”) .子程序 _按钮2_被单击, , , 开源作者:z573277679 .局部变量 i, 整数型 .局部变量 t_start, 整数型 .局部变量 t_total, 整数型 .局部变量 成功次数, 整数型 .局部变量 图片, 字节集 调试输出 (“---------------- [开始压力测试] ----------------”) t_total = 0 成功次数 = 0 .计次循环首 (100, i) t_start = 取启动时间 () 图片 = DXGI_截图 () .如果真 (取字节集长度 (图片) > 0) t_total = t_total + 取启动时间 () - t_start 成功次数 = 成功次数 + 1 .如果真结束 .如果真 (i % 10 = 0) 调试输出 (“进度: ” + 到文本 (i) + “/100...”) 处理事件 () .如果真结束 .计次循环尾 () 调试输出 (“有效帧数: ” + 到文本 (成功次数)) .如果真 (成功次数 > 0) 调试输出 (“平均耗时: ” + 到文本 (t_total ÷ 成功次数) + “ ms / 帧”) .如果真结束 .子程序 __启动窗口_创建完毕, , , 开源作者:z573277679 内部_初始化 ()