补完调试信息
This commit is contained in:
parent
76ca736824
commit
432502e933
@ -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")
|
||||
|
||||
|
||||
@ -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("❌ 纹理对象为空")
|
||||
|
||||
Loading…
Reference in New Issue
Block a user