vr高帧率版本修复

This commit is contained in:
Rowland 2025-09-28 10:41:44 +08:00
parent bb6eee2250
commit 1c356ed6dc
2 changed files with 348 additions and 106 deletions

View File

@ -132,6 +132,11 @@ class VRManager(DirectObject):
self.submit_failures = 0
self.pose_failures = 0
# OpenVR 帧ID跟踪防止重复提交
self.openvr_frame_id = 0
self.left_eye_last_render_frame = -1
self.right_eye_last_render_frame = -1
# 高级性能监控
self.performance_monitoring = True # 是否启用性能监控
self.debug_output_enabled = True # 是否启用调试输出
@ -898,26 +903,36 @@ class VRManager(DirectObject):
if self.vr_task:
self.world.taskMgr.remove(self.vr_task)
self.vr_task = self.world.taskMgr.add(self._update_vr, "update_vr")
print("✓ VR更新任务已启动")
# 设置高优先级sort=-1000确保在渲染之前执行参考 panda3d-openvr
self.vr_task = self.world.taskMgr.add(self._update_vr, "update_vr", sort=-1000)
print("✓ VR更新任务已启动高优先级sort=-1000")
def _update_vr(self, task):
"""VR更新任务 - 每帧调用"""
"""VR更新任务 - 每帧调用(参考 panda3d-openvr 架构)"""
if not self.vr_enabled or not self.vr_system:
return task.cont
try:
# 📌 第一件事waitGetPoses 阻塞等待 VSync参考 panda3d-openvr
# 这会阻塞整个任务,确保每个 VSync 周期只执行一次
should_call_waitgetposes = (
not self.vr_test_mode or # 普通VR模式总是需要
self.test_mode_wait_poses # 测试模式:仅当启用姿态等待时
)
if should_call_waitgetposes:
self._wait_get_poses_immediate()
# 立即更新手柄,使用最新姿态(避免过时数据)
self.update_tracked_devices()
# 性能监控
self.frame_count += 1
# 🚀 手动垃圾回收控制 - 避免16-19帧周期性峰值
self._manual_gc_control()
# 🚀 自动启用性能模式 - 减少计时对象创建
if not self.performance_mode_enabled and self.frame_count >= self.performance_mode_trigger_frame:
self.performance_mode_enabled = True
print(f"🎯 性能模式已启用 (帧#{self.frame_count}) - 禁用详细监控以提升性能")
print(" 现在将减少每帧对象创建显著提升VR性能稳定性")
if self.frame_count <= self.performance_mode_trigger_frame + 5: # 只输出一次
print(f"🎯 性能模式已启用 (帧#{self.frame_count}) - 禁用详细监控以提升性能")
# 记录帧时间
self._track_frame_time()
@ -932,36 +947,31 @@ class VRManager(DirectObject):
self.last_fps_check = self.frame_count
self.last_fps_time = current_time
# 更新系统性能指标
self._update_performance_metrics()
# 更新GPU渲染时间统计
if self.enable_gpu_timing:
self._get_gpu_frame_timing()
# 🚀 Running Start策略WaitGetPoses在Submit后调用此处只更新相机
# 不在此处调用WaitGetPoses避免错过VSync窗口
self.poses_updated_in_task = True
# 使用上一帧获取的姿态更新相机
# 📌 使用刚获取的姿态更新相机(而不是旧姿态)
self._update_camera_poses()
# 输出策略信息(仅第一次)
if not hasattr(self, '_running_start_logged'):
print("✓ Running Start模式已启用 - WaitGetPoses在Submit后调用")
self._running_start_logged = True
if not hasattr(self, '_new_architecture_logged'):
print("✅ 新架构已启用 - waitGetPoses 在任务开始阻塞,参考 panda3d-openvr")
print(" 这确保每个 VSync 周期只渲染一次,解决 AlreadySubmitted 错误")
self._new_architecture_logged = True
# 1. 更新手柄和其他跟踪设备
self.update_tracked_devices()
# 2. 更新VR动作状态
# 更新VR动作状态
self.action_manager.update_actions()
# 3. 更新VR交互系统
# 更新VR交互系统
self.interaction_manager.update()
# 🚀 阶段2&3渲染同步和纹理提交替代DrawCallback
self._handle_vr_rendering_and_submit()
# 更新系统性能指标(减少频率)
if self.frame_count % 30 == 1: # 每30帧更新一次减少开销
self._update_performance_metrics()
# 更新GPU渲染时间统计减少频率
if self.enable_gpu_timing and self.frame_count % 60 == 1:
self._get_gpu_frame_timing()
# 🚀 手动垃圾回收控制 - 避免16-19帧周期性峰值
self._manual_gc_control()
# 定期输出性能报告 - 默认10秒间隔
report_interval = getattr(self, 'performance_report_interval', 600)
@ -975,47 +985,15 @@ class VRManager(DirectObject):
return task.cont
def _handle_vr_rendering_and_submit(self):
"""VR帧管理 - DrawCallback现在处理实际渲染和提交"""
def _sync_gpu_if_needed(self):
"""可选的GPU同步 - 仅在需要时使用"""
try:
import time
# 记录帧处理开始时间
frame_start_time = time.perf_counter()
# DrawCallback会处理实际的渲染和纹理提交
# 这里主要处理帧管理和诊断
# 同步等待GPU完成如果需要
gsg = self.world.win.getGsg()
if gsg:
gsg.getEngine().syncFrame()
# 计算帧处理时间
frame_time = (time.perf_counter() - frame_start_time) * 1000
# Running Start的备用逻辑DrawCallback可能已处理
# 确保每帧都有姿态获取
if not hasattr(self, '_waitgetposes_called_this_frame') or not self._waitgetposes_called_this_frame:
pose_start = time.perf_counter()
self._wait_get_poses_immediate()
self.wait_poses_time = (time.perf_counter() - pose_start) * 1000
self._waitgetposes_called_this_frame = True
# 重置标记,准备下一帧
self.world.taskMgr.doMethodLater(0.001, self._reset_waitgetposes_flag, "reset_waitgetposes_flag")
# 调试信息(仅在启用时)
if self.debug_output_enabled and self.frame_count % 300 == 1:
print(f"🎯 帧#{self.frame_count} DrawCallback模式:")
print(f" 帧管理时间: {frame_time:.2f}ms")
print(f" 渲染由回调处理: 左眼={self.left_render_count}, 右眼={self.right_render_count}")
print(f" 姿态获取: {self.wait_poses_time:.2f}ms")
except Exception as e:
print(f"❌ VR帧管理异常: {e}")
import traceback
traceback.print_exc()
print(f"❌ GPU同步异常: {e}")
def simple_left_cb(self, cbdata):
"""简化的左眼渲染回调 - 精确控制渲染和提交"""
@ -1033,25 +1011,25 @@ class VRManager(DirectObject):
# 记录渲染次数
self.left_render_count += 1
# 检查避免重复提交
current_frame = getattr(self, 'frame_count', 0)
if not hasattr(self, '_left_submitted_frame'):
self._left_submitted_frame = -1
# 📌 OpenVR 帧边界检查:防止同一 OpenVR 帧内重复渲染
if self.left_eye_last_render_frame == self.openvr_frame_id:
return # 已在当前 OpenVR 帧渲染过,跳过
if self._left_submitted_frame != current_frame:
self._left_submitted_frame = current_frame
# 🔧 OpenVR最佳实践左眼只渲染不立即提交
# 基于官方hellovr示例两眼都渲染完后再批量提交
self.left_eye_last_render_frame = self.openvr_frame_id
# 🔧 渐进式VR功能测试根据调试标志决定是否提交纹理
should_submit = not self.vr_test_mode or self.test_mode_submit_texture
# 渐进式VR功能测试单独启用纹理提交时保留原逻辑
should_submit = self.vr_test_mode and self.test_mode_submit_texture and not self.test_mode_wait_poses
if should_submit:
# 渲染后立即提交纹理(普通模式或测试模式启用提交时)
if self.vr_compositor and self.vr_left_texture:
self.submit_texture(openvr.Eye_Left, self.vr_left_texture)
if should_submit:
# 测试模式:单独启用纹理提交时的兼容模式
if self.vr_compositor and self.vr_left_texture:
self.submit_texture(openvr.Eye_Left, self.vr_left_texture)
if self.vr_test_mode:
# 测试模式:始终触发屏幕显示更新
self._update_test_display()
if self.vr_test_mode:
# 测试模式:始终触发屏幕显示更新
self._update_test_display()
except Exception as e:
print(f"左眼渲染回调错误: {e}")
@ -1072,33 +1050,56 @@ class VRManager(DirectObject):
# 记录渲染次数
self.right_render_count += 1
# 检查避免重复提交
current_frame = getattr(self, 'frame_count', 0)
if not hasattr(self, '_right_submitted_frame'):
self._right_submitted_frame = -1
# 📌 OpenVR 帧边界检查:防止同一 OpenVR 帧内重复渲染
if self.right_eye_last_render_frame == self.openvr_frame_id:
return # 已在当前 OpenVR 帧渲染过,跳过
if self._right_submitted_frame != current_frame:
self._right_submitted_frame = current_frame
# 🔧 OpenVR最佳实践右眼渲染完成后批量提交两眼纹理
# 基于官方hellovr示例避免分散提交导致的VSync阻塞
self.right_eye_last_render_frame = self.openvr_frame_id
# 🔧 渐进式VR功能测试根据调试标志决定启用哪些功能
should_submit = not self.vr_test_mode or self.test_mode_submit_texture
should_wait_poses = not self.vr_test_mode or self.test_mode_wait_poses
# 🔧 渐进式VR功能测试根据调试标志决定启用哪些功能
should_batch_submit = not self.vr_test_mode or self.test_mode_submit_texture
should_wait_poses = not self.vr_test_mode or self.test_mode_wait_poses
if should_submit:
# 渲染后立即提交纹理(普通模式或测试模式启用提交时)
# 特殊处理:测试模式单独启用功能时的兼容模式
if self.vr_test_mode:
if self.test_mode_submit_texture and not self.test_mode_wait_poses:
# 单独测试纹理提交:使用原来的分散提交方式
if self.vr_compositor and self.vr_right_texture:
self.submit_texture(openvr.Eye_Right, self.vr_right_texture)
if should_wait_poses:
# Running Start右眼提交后立即获取姿态普通模式或测试模式启用时
if not hasattr(self, '_waitgetposes_called_this_frame') or not self._waitgetposes_called_this_frame:
self._wait_get_poses_immediate()
self._waitgetposes_called_this_frame = True
self.world.taskMgr.doMethodLater(0.001, self._reset_waitgetposes_flag, "reset_waitgetposes_flag")
# 🚀 测试模式也需要PostPresentHandoff避免36FPS
try:
if hasattr(self.vr_compositor, 'postPresentHandoff'):
self.vr_compositor.postPresentHandoff()
elif hasattr(self.vr_compositor, 'PostPresentHandoff'):
self.vr_compositor.PostPresentHandoff()
except Exception as e:
pass # 测试模式静默忽略错误
should_batch_submit = False
elif self.test_mode_wait_poses and not self.test_mode_submit_texture:
# 单独测试姿态等待:不提交纹理
should_batch_submit = False
if self.vr_test_mode:
# 测试模式始终更新性能HUD
self._update_test_performance_hud()
if should_batch_submit:
# 🚀 OpenVR最佳实践批量提交两眼纹理
# 这是解决36FPS问题的关键修复
self._batch_submit_textures()
# 🔧 关键修复移除Submit后立即WaitGetPoses的错误实现
# 根据OpenVR官方文档"Calling WaitGetPoses immediately after Submit is conspicuously wrong"
# WaitGetPoses应该在下一帧开始时通过update_vr_task调用不是Submit后立即调用
#
# if should_wait_poses:
# # 错误的实现Submit后立即获取姿态导致36FPS
# self._wait_get_poses_immediate() # ← 这是36FPS的根本原因
#
# 正确的实现让update_vr_task在下一帧开始时调用WaitGetPoses
if self.vr_test_mode:
# 测试模式始终更新性能HUD
self._update_test_performance_hud()
except Exception as e:
print(f"右眼渲染回调错误: {e}")
@ -1165,6 +1166,9 @@ class VRManager(DirectObject):
# 渲染姿态用于绘制游戏姿态用于逻辑避免ATW过度补偿
result = self.vr_compositor.waitGetPoses(self.poses, self.game_poses)
# 📌 waitGetPoses 成功后立即递增 OpenVR 帧ID新帧开始
self.openvr_frame_id += 1
# 结束计时
wait_time = self._end_timing(timing)
@ -1204,10 +1208,15 @@ class VRManager(DirectObject):
self._return_pooled_matrix(self.controller_poses[device_id])
del self.controller_poses[device_id]
# 🔧 关键修复:立即更新手柄和跟踪设备
# Running Start模式下必须在WaitGetPoses后立即更新避免手柄消失
self.update_tracked_devices()
# 调试信息 - 仅在第一次成功时输出
if not hasattr(self, '_dual_pose_mode_logged') and valid_poses > 0:
print(f"✅ 双姿态立即获取模式启用 - 有效姿态数: {valid_poses}")
print(" 渲染姿态用于绘制游戏姿态用于逻辑防止ATW过度补偿")
print(" 手柄和跟踪设备在WaitGetPoses后立即更新")
self._dual_pose_mode_logged = True
except Exception as e:
@ -1500,7 +1509,8 @@ class VRManager(DirectObject):
# VR性能优化使用Running Start模式Valve最佳实践
print("🚀 VR性能优化Running Start模式已启用")
print(" 优势Submit后立即获取姿态避免错过VSync窗口")
print(" 优势在帧开始时获取姿态提供VSync前3ms的渲染时间")
print(" 注意Submit后立即调用WaitGetPoses是错误实现")
self.set_prediction_time(11.0) # 11ms预测时间 - OpenVR标准值平衡准确性和延迟
# 🚀 动态调整Qt Timer频率以支持VR
@ -1835,8 +1845,8 @@ class VRManager(DirectObject):
# 显示Running Start模式信息
print(f"🎯 Running Start模式:")
print(f" 模式: Valve Running Start - Submit后立即获取姿态")
print(f" 优势: 避免VSync延迟提升VR性能")
print(f" 模式: Valve Running Start - 帧开始时获取姿态")
print(f" 优势: VSync前3ms获取姿态提供充足渲染时间")
print(f" 预测时间: {self.use_prediction_time * 1000:.1f}ms")
# 分析最大瓶颈
@ -1866,11 +1876,11 @@ class VRManager(DirectObject):
recommendations = []
# FPS相关建议
if stats['vr_fps'] < 72:
if stats['vr_fps'] < 60:
recommendations.append(" ⚠️ VR帧率过低可能影响体验")
# 帧时间相关建议
if stats['frame_time_avg'] > 13.9: # 72fps = 13.9ms
if stats['frame_time_avg'] > 16.7: # 60fps = 16.7ms
recommendations.append(" ⚠️ 平均帧时间过高,建议降低渲染质量")
if stats['frame_time_max'] > 50:
@ -2658,7 +2668,7 @@ class VRManager(DirectObject):
# Running Start模式信息
print("🎯 Running Start模式:")
print(f" 预测时间: {self.use_prediction_time * 1000:.1f}ms")
print(f" 模式: Valve Running Start - Submit后立即获取姿态")
print(f" 模式: Valve Running Start - 帧开始时获取姿态")
# 测试管线统计
if self.enable_pipeline_monitoring:
@ -3437,6 +3447,13 @@ class VRManager(DirectObject):
print("❌ VR初始化失败")
return False
# 🔧 关键修复:确保测试模式的纹理资源已初始化
# 这解决了测试模式纹理提交失败导致的36FPS问题
print("🔧 检查VR测试模式纹理资源...")
if not self._ensure_test_mode_textures():
print("❌ VR测试模式纹理资源初始化失败")
return False
# 设置测试模式
self.vr_test_mode = True
self.test_display_mode = display_mode
@ -3483,6 +3500,157 @@ class VRManager(DirectObject):
traceback.print_exc()
return False
def _ensure_test_mode_textures(self):
"""确保VR测试模式的纹理资源已正确初始化
这解决了测试模式启用纹理提交时的36FPS问题
- VR测试模式可能跳过了VR渲染缓冲区的初始化
- submit_texture()需要有效的texture ID和OpenVR Texture对象
- 如果未初始化会导致提交失败造成帧率减半
"""
try:
print(" 检查VR渲染缓冲区...")
# 检查VR渲染缓冲区是否存在
buffers_exist = (
hasattr(self, 'vr_left_eye_buffer') and self.vr_left_eye_buffer and
hasattr(self, 'vr_right_eye_buffer') and self.vr_right_eye_buffer
)
if not buffers_exist:
print(" ⚠️ VR渲染缓冲区不存在正在创建...")
if not self._setup_vr_render_buffers():
print(" ❌ VR渲染缓冲区创建失败")
return False
print(" ✅ VR渲染缓冲区创建成功")
else:
print(" ✅ VR渲染缓冲区已存在")
# 检查纹理ID是否已缓存
print(" 检查纹理ID缓存...")
texture_ids_cached = (
hasattr(self, 'left_texture_id') and self.left_texture_id and self.left_texture_id > 0 and
hasattr(self, 'right_texture_id') and self.right_texture_id and self.right_texture_id > 0
)
if not texture_ids_cached:
print(" ⚠️ 纹理ID未缓存正在准备纹理...")
if not self._prepare_and_cache_textures():
print(" ❌ 纹理准备和缓存失败")
return False
print(f" ✅ 纹理ID缓存成功 - 左眼:{self.left_texture_id}, 右眼:{self.right_texture_id}")
else:
print(f" ✅ 纹理ID已缓存 - 左眼:{self.left_texture_id}, 右眼:{self.right_texture_id}")
# 检查OpenVR Texture对象是否已创建
print(" 检查OpenVR Texture对象...")
ovr_textures_exist = (
hasattr(self, '_left_ovr_texture') and self._left_ovr_texture and
hasattr(self, '_right_ovr_texture') and self._right_ovr_texture
)
if not ovr_textures_exist:
print(" ⚠️ OpenVR Texture对象未创建正在创建...")
self._create_cached_ovr_textures()
print(" ✅ OpenVR Texture对象创建成功")
else:
print(" ✅ OpenVR Texture对象已存在")
print(" ✅ VR测试模式纹理资源检查完成可安全启用纹理提交")
return True
except Exception as e:
print(f" ❌ VR测试模式纹理资源检查失败: {e}")
import traceback
traceback.print_exc()
return False
def _create_cached_ovr_textures(self):
"""创建缓存的OpenVR Texture对象 - 避免每帧创建新对象"""
try:
import openvr
self._left_ovr_texture = openvr.Texture_t()
self._right_ovr_texture = openvr.Texture_t()
# 设置固定属性(这些不变)
self._left_ovr_texture.eType = openvr.TextureType_OpenGL
self._left_ovr_texture.eColorSpace = openvr.ColorSpace_Gamma
self._right_ovr_texture.eType = openvr.TextureType_OpenGL
self._right_ovr_texture.eColorSpace = openvr.ColorSpace_Gamma
print("✅ OpenVR Texture对象缓存已创建")
except Exception as e:
print(f"⚠️ OpenVR Texture对象创建失败: {e}")
# 不抛出异常,使用备用方案
def _batch_submit_textures(self):
"""批量提交两眼纹理 - OpenVR最佳实践
基于官方hellovr示例的实现
- 两眼都渲染完成后快速连续提交
- 减少submit阻塞时间避免错过VSync窗口
- 这是解决36FPS问题的关键
"""
try:
if not self.vr_compositor:
return False
# 检查纹理是否准备好
if not (self.vr_left_texture and self.vr_right_texture):
return False
# 🚀 关键:快速连续提交两眼,最小化阻塞时间
# 这符合OpenVR官方示例的做法
success_left = False
success_right = False
# 提交左眼纹理
try:
self.submit_texture(openvr.Eye_Left, self.vr_left_texture)
success_left = True
except Exception as e:
print(f"❌ 批量提交左眼失败: {e}")
# 立即提交右眼纹理(不等待)
try:
self.submit_texture(openvr.Eye_Right, self.vr_right_texture)
success_right = True
except Exception as e:
print(f"❌ 批量提交右眼失败: {e}")
# 🚀 关键修复调用PostPresentHandoff解除compositor阻塞
# 这是解决36FPS问题的核心 - 确保compositor不会等待VSync
if success_left and success_right:
try:
# PostPresentHandoff告诉compositor我们已完成帧处理
# 防止compositor等待下一个VSync周期
if hasattr(self.vr_compositor, 'postPresentHandoff'):
self.vr_compositor.postPresentHandoff()
elif hasattr(self.vr_compositor, 'PostPresentHandoff'):
self.vr_compositor.PostPresentHandoff()
else:
# 备用方案如果没有PostPresentHandoff记录警告
if not hasattr(self, '_post_present_warning_logged'):
print("⚠️ PostPresentHandoff方法未找到可能影响时序")
self._post_present_warning_logged = True
except Exception as handoff_error:
if not hasattr(self, '_handoff_error_logged'):
print(f"⚠️ PostPresentHandoff调用失败: {handoff_error}")
self._handoff_error_logged = True
# 记录批量提交状态(仅首次成功时)
if not hasattr(self, '_batch_submit_success_logged'):
print("✅ OpenVR批量提交模式+PostPresentHandoff已启用")
print(" 这应该解决36FPS → 72FPS的问题")
self._batch_submit_success_logged = True
return True
else:
return False
except Exception as e:
print(f"❌ 批量提交纹理失败: {e}")
return False
def disable_vr_test_mode(self):
"""禁用VR测试模式"""
try:

View File

@ -503,6 +503,26 @@ class MainWindow(QMainWindow):
self.vrTestModeAction.setCheckable(True)
self.vrTestModeAction.setChecked(False) # 默认关闭
# VR测试模式调试子菜单
self.vrTestDebugMenu = self.vrDebugMenu.addMenu('测试模式调试')
# 渐进式功能开关
self.vrTestSubmitTextureAction = self.vrTestDebugMenu.addAction('启用纹理提交')
self.vrTestSubmitTextureAction.setCheckable(True)
self.vrTestSubmitTextureAction.setChecked(False) # 默认关闭
self.vrTestWaitPosesAction = self.vrTestDebugMenu.addAction('启用姿态等待')
self.vrTestWaitPosesAction.setCheckable(True)
self.vrTestWaitPosesAction.setChecked(False) # 默认关闭
self.vrTestDebugMenu.addSeparator()
# 快捷测试预设
self.vrTestStep1Action = self.vrTestDebugMenu.addAction('步骤1: 只启用纹理提交')
self.vrTestStep2Action = self.vrTestDebugMenu.addAction('步骤2: 只启用姿态等待')
self.vrTestStep3Action = self.vrTestDebugMenu.addAction('步骤3: 同时启用两者')
self.vrTestResetAction = self.vrTestDebugMenu.addAction('重置: 禁用所有功能')
self.vrDebugSettingsAction = self.vrDebugMenu.addAction('调试设置...')
# 初始状态下禁用退出VR选项
@ -984,6 +1004,15 @@ class MainWindow(QMainWindow):
self.vrPoseUpdateTaskAction.triggered.connect(lambda: self.onSetVRPoseStrategy('update_task'))
self.vrTestPipelineAction.triggered.connect(self.onTestVRPipeline)
self.vrTestModeAction.triggered.connect(self.onToggleVRTestMode)
# 连接VR测试模式调试菜单事件
self.vrTestSubmitTextureAction.triggered.connect(self.onToggleVRTestSubmitTexture)
self.vrTestWaitPosesAction.triggered.connect(self.onToggleVRTestWaitPoses)
self.vrTestStep1Action.triggered.connect(lambda: self.onSetVRTestStep(1))
self.vrTestStep2Action.triggered.connect(lambda: self.onSetVRTestStep(2))
self.vrTestStep3Action.triggered.connect(lambda: self.onSetVRTestStep(3))
self.vrTestResetAction.triggered.connect(lambda: self.onSetVRTestStep(0))
self.vrDebugSettingsAction.triggered.connect(self.onShowVRDebugSettings)
@ -2554,6 +2583,51 @@ class MainWindow(QMainWindow):
self.vrTestModeAction.setChecked(False)
QMessageBox.critical(self, "错误", f"切换VR测试模式时发生错误\n{str(e)}")
def onToggleVRTestSubmitTexture(self):
"""切换VR测试模式纹理提交功能"""
try:
if hasattr(self.world, 'vr_manager') and self.world.vr_manager:
enabled = self.vrTestSubmitTextureAction.isChecked()
self.world.vr_manager.set_test_mode_features(submit_texture=enabled)
except Exception as e:
QMessageBox.critical(self, "错误", f"设置纹理提交功能时发生错误:\n{str(e)}")
def onToggleVRTestWaitPoses(self):
"""切换VR测试模式姿态等待功能"""
try:
if hasattr(self.world, 'vr_manager') and self.world.vr_manager:
enabled = self.vrTestWaitPosesAction.isChecked()
self.world.vr_manager.set_test_mode_features(wait_poses=enabled)
except Exception as e:
QMessageBox.critical(self, "错误", f"设置姿态等待功能时发生错误:\n{str(e)}")
def onSetVRTestStep(self, step):
"""设置VR测试步骤"""
try:
if hasattr(self.world, 'vr_manager') and self.world.vr_manager:
if step == 0: # 重置
self.world.vr_manager.set_test_mode_features(submit_texture=False, wait_poses=False)
self.vrTestSubmitTextureAction.setChecked(False)
self.vrTestWaitPosesAction.setChecked(False)
QMessageBox.information(self, "VR测试", "已重置为基线状态:两个功能都禁用")
elif step == 1: # 只启用纹理提交
self.world.vr_manager.set_test_mode_features(submit_texture=True, wait_poses=False)
self.vrTestSubmitTextureAction.setChecked(True)
self.vrTestWaitPosesAction.setChecked(False)
QMessageBox.information(self, "VR测试", "步骤1只启用纹理提交\n观察FPS变化来判断submit_texture是否影响性能")
elif step == 2: # 只启用姿态等待
self.world.vr_manager.set_test_mode_features(submit_texture=False, wait_poses=True)
self.vrTestSubmitTextureAction.setChecked(False)
self.vrTestWaitPosesAction.setChecked(True)
QMessageBox.information(self, "VR测试", "步骤2只启用姿态等待\n观察FPS变化来判断waitGetPoses是否影响性能")
elif step == 3: # 同时启用两者
self.world.vr_manager.set_test_mode_features(submit_texture=True, wait_poses=True)
self.vrTestSubmitTextureAction.setChecked(True)
self.vrTestWaitPosesAction.setChecked(True)
QMessageBox.information(self, "VR测试", "步骤3同时启用两者\n这应该完全复现普通VR模式的36FPS问题")
except Exception as e:
QMessageBox.critical(self, "错误", f"设置VR测试步骤时发生错误\n{str(e)}")
def setup_main_window(world,path = None):
"""设置主窗口的便利函数"""
app = QApplication.instance()