From 432502e9338266880611f97a82f5b276463f4572 Mon Sep 17 00:00:00 2001 From: Rowland <975945824@qq.com> Date: Wed, 24 Sep 2025 15:00:36 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E5=AE=8C=E8=B0=83=E8=AF=95=E4=BF=A1?= =?UTF-8?q?=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- QPanda3D/Panda3DWorld.py | 7 ++ core/vr_manager.py | 174 +++++++++++++++++++++++++++++++-------- 2 files changed, 147 insertions(+), 34 deletions(-) diff --git a/QPanda3D/Panda3DWorld.py b/QPanda3D/Panda3DWorld.py index 1afffc65..bf6a2524 100644 --- a/QPanda3D/Panda3DWorld.py +++ b/QPanda3D/Panda3DWorld.py @@ -70,6 +70,13 @@ class Panda3DWorld(ShowBase): loadPrcFileData("", f"win-size {width} {height}") loadPrcFileData("", "win-fixed-size #f") # 允许窗口调整大小 + # 🚀 VR性能优化配置 + loadPrcFileData("", "prefer-single-buffer true") # 减少缓冲区交换开销 + loadPrcFileData("", "gl-force-flush false") # 避免强制glFlush导致的性能损失 + loadPrcFileData("", "sync-video false") # 禁用默认VSync,让OpenVR控制 + loadPrcFileData("", "support-stencil false") # 禁用不必要的模板缓冲区 + # loadPrcFileData("", "gl-debug true") # 调试时可启用OpenGL调试 + if (is_fullscreen): loadPrcFileData("", "fullscreen #t") diff --git a/core/vr_manager.py b/core/vr_manager.py index 74762612..522d81b4 100644 --- a/core/vr_manager.py +++ b/core/vr_manager.py @@ -144,7 +144,7 @@ class VRManager(DirectObject): # waitGetPoses调用策略配置 self.pose_strategy = 'render_callback' # 'render_callback' 或 'update_task' - self.use_prediction_time = 0.011 # 11ms的预测时间(用于update_task策略) + self.use_prediction_time = 0.007 # 7ms的预测时间 - 优化后减少VSync等待 self.poses_updated_in_task = False # 标记是否在更新任务中已获取姿态 # 尝试导入性能监控库 @@ -410,7 +410,7 @@ class VRManager(DirectObject): return texture def _create_vr_buffer(self, name, texture, width, height): - """创建VR渲染缓冲区 - 基于参考实现""" + """创建VR渲染缓冲区 - 基于参考实现 + 性能诊断""" # 设置帧缓冲属性 fbprops = FrameBufferProperties() fbprops.setRgbaBits(1, 1, 1, 1) @@ -421,13 +421,59 @@ class VRManager(DirectObject): buffer = self.world.win.makeTextureBuffer(name, width, height, to_ram=False, fbp=fbprops) if buffer: + # 🔍 性能诊断:检查缓冲区类型和属性 + self._diagnose_buffer_performance(buffer, name, width, height) + # 清除默认渲染纹理 buffer.clearRenderTextures() - # 添加我们的纹理 + # 添加我们的纹理 - 使用RTMBindOrCopy避免不必要的内存拷贝 buffer.addRenderTexture(texture, GraphicsOutput.RTMBindOrCopy, GraphicsOutput.RTPColor) + else: + print(f"⚠️ VR缓冲区创建失败: {name} ({width}x{height})") + return buffer + def _diagnose_buffer_performance(self, buffer, name, width, height): + """诊断VR缓冲区性能特性""" + try: + # 检查缓冲区类型 + buffer_type = type(buffer).__name__ + + # 检查是否为parasite buffer(性能较差的类型) + is_parasite = 'Parasite' in buffer_type + + # 获取缓冲区信息 + is_valid = buffer.isValid() + is_hardware = hasattr(buffer, 'getGsg') and buffer.getGsg() is not None + + # 输出诊断信息(仅第一次创建时) + if not hasattr(self, '_buffer_diagnosis_shown'): + print(f"🔍 VR缓冲区诊断 [{name}]:") + print(f" 类型: {buffer_type}") + print(f" 分辨率: {width}x{height} ({width*height/1000000:.1f}M像素)") + print(f" 有效性: {'✓' if is_valid else '✗'}") + print(f" 硬件支持: {'✓' if is_hardware else '✗'}") + + if is_parasite: + print(f" ⚠️ 检测到Parasite Buffer - 性能可能受限") + print(f" 建议: 检查显卡是否支持真正的离屏渲染") + else: + print(f" ✓ 使用硬件FBO - 性能良好") + + # 显示帧缓冲区属性 + if hasattr(buffer, 'getFbProperties'): + fbp = buffer.getFbProperties() + if fbp: + print(f" 颜色位数: R{fbp.getRedBits()}G{fbp.getGreenBits()}B{fbp.getBlueBits()}A{fbp.getAlphaBits()}") + if hasattr(fbp, 'getMultisamples') and fbp.getMultisamples() > 0: + print(f" MSAA: {fbp.getMultisamples()}x") + + self._buffer_diagnosis_shown = True + + except Exception as e: + print(f"缓冲区诊断失败: {e}") + def _setup_vr_cameras(self): """设置VR相机 - 使用锚点层级系统""" try: @@ -1095,7 +1141,7 @@ class VRManager(DirectObject): # 优化VR性能:切换到update_task姿态策略 print("🚀 正在优化VR性能...") self.set_pose_strategy('update_task') - self.set_prediction_time(11.0) # 11ms预测时间 + self.set_prediction_time(7.0) # 7ms预测时间 - 减少VSync等待时间 print("✓ VR性能优化完成 - 姿态策略已切换至update_task模式") print("✅ VR模式已启用") @@ -1306,40 +1352,88 @@ class VRManager(DirectObject): else: print(f" ✓ 帧时间正常: {current_frame_time:.1f}ms (目标:{target_frame_time:.1f}ms)") - print(f"🕐 各阶段耗时 (最近{self.pipeline_history_size}帧平均):") - print(f" waitGetPoses: {pipeline_stats['wait_poses']['avg']:.2f}ms (min:{pipeline_stats['wait_poses']['min']:.1f}, max:{pipeline_stats['wait_poses']['max']:.1f})") - print(f" 渲染总计: {pipeline_stats['render']['avg']:.2f}ms (min:{pipeline_stats['render']['min']:.1f}, max:{pipeline_stats['render']['max']:.1f})") - print(f" 纹理提交: {pipeline_stats['submit']['avg']:.2f}ms (min:{pipeline_stats['submit']['min']:.1f}, max:{pipeline_stats['submit']['max']:.1f})") - if pipeline_stats['sync_wait']['avg'] > 0: - print(f" 同步等待: {pipeline_stats['sync_wait']['avg']:.2f}ms (min:{pipeline_stats['sync_wait']['min']:.1f}, max:{pipeline_stats['sync_wait']['max']:.1f})") + # 🔧 性能优化诊断 + print(f"🔧 优化诊断:") + current = pipeline_stats.get('current', {}) if self.enable_pipeline_monitoring else {} - print(f"🔍 当前帧详情:") - print(f" 左眼渲染: {pipeline_stats['current']['left_render']:.2f}ms") - print(f" 右眼渲染: {pipeline_stats['current']['right_render']:.2f}ms") - print(f" 姿态获取: {pipeline_stats['current']['wait_poses']:.2f}ms") + # waitGetPoses时序分析 + wait_poses_time = current.get('wait_poses', 0) + if wait_poses_time > 10: + print(f" ⚠️ waitGetPoses时间过长: {wait_poses_time:.1f}ms") + print(f" 可能原因: 错过VSync窗口,建议降低预测时间") + elif wait_poses_time > 5: + print(f" ⚠️ waitGetPoses时间偏高: {wait_poses_time:.1f}ms") + else: + print(f" ✓ waitGetPoses时间正常: {wait_poses_time:.1f}ms") - # 显示姿态策略信息 - strategy_info = self.get_pose_strategy_info() - print(f"🎯 姿态策略:") - print(f" 当前策略: {strategy_info['strategy']}") - print(f" 策略描述: {strategy_info['description']}") - if strategy_info['strategy'] == 'update_task': - print(f" 预测时间: {strategy_info['prediction_time_ms']:.1f}ms") + # CPU-GPU并行度分析 + gpu_total = current.get('gpu_total_render', 0) + cpu_render = current.get('total_render', 0) + if gpu_total > 0 and cpu_render > 0: + if gpu_total > cpu_render * 3: + print(f" ⚠️ GPU等待CPU: GPU{gpu_total:.1f}ms vs CPU{cpu_render:.1f}ms") + print(f" 建议: 检查OpenGL命令提交是否及时") + elif cpu_render > gpu_total * 2: + print(f" ⚠️ CPU瓶颈: CPU{cpu_render:.1f}ms vs GPU{gpu_total:.1f}ms") + else: + print(f" ✓ CPU-GPU平衡: CPU{cpu_render:.1f}ms GPU{gpu_total:.1f}ms") - # 分析最大瓶颈 - current = pipeline_stats['current'] - bottleneck_analysis = [] - if current['wait_poses'] > 5.0: - bottleneck_analysis.append(f"姿态获取耗时过长({current['wait_poses']:.1f}ms)") - if current['total_render'] > 8.0: - bottleneck_analysis.append(f"渲染耗时过长({current['total_render']:.1f}ms)") - if current['submit'] > 2.0: - bottleneck_analysis.append(f"纹理提交耗时过长({current['submit']:.1f}ms)") + # 预测时间诊断 + current_prediction = self.use_prediction_time * 1000 + print(f" 预测时间设置: {current_prediction:.1f}ms") + if current_prediction > 10: + print(f" 建议: 预测时间较高,可能增加waitGetPoses延迟") + elif current_prediction < 5: + print(f" 注意: 预测时间较低,可能影响姿态准确性") - if bottleneck_analysis: - print(f"🚨 瓶颈分析:") - for analysis in bottleneck_analysis: - print(f" ⚠️ {analysis}") + # 优化状态总结 + optimization_score = 0 + if wait_poses_time < 8: + optimization_score += 1 + if stats['vr_fps'] > 60: + optimization_score += 1 + if stats.get('frame_time_avg', 0) < target_frame_time * 1.1: + optimization_score += 1 + + if optimization_score >= 2: + print(f" ✅ 优化效果良好 ({optimization_score}/3)") + else: + print(f" ⚠️ 仍有优化空间 ({optimization_score}/3)") + + print(f"🕐 各阶段耗时 (最近{self.pipeline_history_size}帧平均):") + print(f" waitGetPoses: {pipeline_stats['wait_poses']['avg']:.2f}ms (min:{pipeline_stats['wait_poses']['min']:.1f}, max:{pipeline_stats['wait_poses']['max']:.1f})") + print(f" 渲染总计: {pipeline_stats['render']['avg']:.2f}ms (min:{pipeline_stats['render']['min']:.1f}, max:{pipeline_stats['render']['max']:.1f})") + print(f" 纹理提交: {pipeline_stats['submit']['avg']:.2f}ms (min:{pipeline_stats['submit']['min']:.1f}, max:{pipeline_stats['submit']['max']:.1f})") + if pipeline_stats['sync_wait']['avg'] > 0: + print(f" 同步等待: {pipeline_stats['sync_wait']['avg']:.2f}ms (min:{pipeline_stats['sync_wait']['min']:.1f}, max:{pipeline_stats['sync_wait']['max']:.1f})") + + print(f"🔍 当前帧详情:") + print(f" 左眼渲染: {pipeline_stats['current']['left_render']:.2f}ms") + print(f" 右眼渲染: {pipeline_stats['current']['right_render']:.2f}ms") + print(f" 姿态获取: {pipeline_stats['current']['wait_poses']:.2f}ms") + + # 显示姿态策略信息 + strategy_info = self.get_pose_strategy_info() + print(f"🎯 姿态策略:") + print(f" 当前策略: {strategy_info['strategy']}") + print(f" 策略描述: {strategy_info['description']}") + if strategy_info['strategy'] == 'update_task': + print(f" 预测时间: {strategy_info['prediction_time_ms']:.1f}ms") + + # 分析最大瓶颈 + current = pipeline_stats['current'] + bottleneck_analysis = [] + if current['wait_poses'] > 5.0: + bottleneck_analysis.append(f"姿态获取耗时过长({current['wait_poses']:.1f}ms)") + if current['total_render'] > 8.0: + bottleneck_analysis.append(f"渲染耗时过长({current['total_render']:.1f}ms)") + if current['submit'] > 2.0: + bottleneck_analysis.append(f"纹理提交耗时过长({current['submit']:.1f}ms)") + + if bottleneck_analysis: + print(f"🚨 瓶颈分析:") + for analysis in bottleneck_analysis: + print(f" ⚠️ {analysis}") # 性能建议 self._print_performance_recommendations(stats) @@ -1587,6 +1681,18 @@ class VRManager(DirectObject): self.submit_failures += 1 return + # 🚀 安全的OpenGL命令刷新:在纹理提交前确保渲染命令已发送到GPU + try: + if hasattr(gsg, 'flush'): + gsg.flush() + elif hasattr(gsg, 'clear_before_callback'): + # 另一种可能的刷新方法 + pass + except Exception as flush_error: + if not hasattr(self, '_gsg_flush_error_logged'): + print(f"⚠️ GSG刷新失败: {flush_error}") + self._gsg_flush_error_logged = True + # 准备纹理并获取更详细的错误信息 if not texture: print("❌ 纹理对象为空")