""" VR对象池和优化系统 负责VR系统中的对象池管理、垃圾回收控制、分辨率缩放和性能模式控制。 """ import gc from panda3d.core import Mat4 class VROptimization: """VR优化系统 - 管理对象池、GC控制、分辨率缩放和性能模式""" def __init__(self, vr_manager): """初始化VR优化系统 Args: vr_manager: VR管理器实例引用 """ self.vr_manager = vr_manager # 对象池属性 self._matrix_pool = [] # Mat4对象池 self._matrix_pool_size = 8 # 池大小,足够处理多个控制器 self._cached_matrices = {} # 设备ID到矩阵的缓存 self._controller_poses_cache = {} # 控制器姿态缓存,避免每帧clear() # OpenVR Texture对象缓存 - 避免每帧创建openvr.Texture_t() self._left_ovr_texture = None # 左眼纹理对象缓存 self._right_ovr_texture = None # 右眼纹理对象缓存 # Python垃圾回收控制 self._gc_control_enabled = True # 是否启用GC控制 self._gc_disabled = False # GC是否被禁用 self._manual_gc_interval = 900 # 每900帧手动触发一次GC (15秒@60fps) - 减少GC频率 self._last_manual_gc_frame = 0 # VR分辨率缩放优化 self.resolution_scale = 0.75 # 默认0.75倍分辨率,性能和质量平衡 self.base_eye_width = 1080 # 原始推荐分辨率 self.base_eye_height = 1200 self.scaled_eye_width = 1080 # 实际使用的缩放后分辨率 self.scaled_eye_height = 1200 # VR质量预设 self.quality_presets = { 'performance': 0.6, # 性能模式 - 约60%分辨率 'balanced': 0.75, # 平衡模式 - 约75%分辨率 'quality': 1.0 # 质量模式 - 100%分辨率 } self.current_quality_preset = 'balanced' # 默认平衡模式 # 性能模式控制 self.performance_mode_enabled = False # 是否启用性能模式 self.performance_mode_trigger_frame = 600 # 600帧后自动启用性能模式 def _initialize_object_pools(self): """初始化对象池 - 修复16-19帧周期性GPU峰值""" try: # 预填充Mat4对象池 for _ in range(self._matrix_pool_size): self._matrix_pool.append(Mat4()) print(f"✅ Mat4对象池初始化完成 - 池大小: {self._matrix_pool_size}") # 🚀 预创建OpenVR Texture对象 - 消除每帧创建openvr.Texture_t()的开销 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 texture_error: print(f"⚠️ OpenVR Texture对象创建失败: {texture_error}") # 不影响整体初始化,但性能可能不是最优 # 启用GC控制 if self._gc_control_enabled: # 禁用自动垃圾回收,改为手动控制 gc.disable() self._gc_disabled = True print("✅ Python垃圾回收已禁用,改为手动控制") except Exception as e: print(f"⚠️ 对象池初始化失败: {e}") def _get_pooled_matrix(self): """从对象池获取Mat4对象""" if self._matrix_pool: return self._matrix_pool.pop() else: # 池为空时创建新对象(不应该发生,但作为备用) return Mat4() def _return_pooled_matrix(self, matrix): """将Mat4对象返回对象池""" if len(self._matrix_pool) < self._matrix_pool_size: # 重置矩阵到单位矩阵 matrix.identMat() self._matrix_pool.append(matrix) def _manual_gc_control(self): """手动垃圾回收控制 - 避免VR渲染期间的GC峰值""" if not self._gc_control_enabled or not self._gc_disabled: return # 🚀 智能GC间隔:性能模式下减少GC频率 current_interval = self._manual_gc_interval if self.performance_mode_enabled: current_interval = self._manual_gc_interval * 2 # 性能模式下间隔翻倍 # 每N帧手动触发一次垃圾回收 if self.vr_manager.frame_count - self._last_manual_gc_frame >= current_interval: # 在非渲染关键时刻触发GC collected = gc.collect() self._last_manual_gc_frame = self.vr_manager.frame_count # 仅在收集到对象时输出信息 if collected > 0: print(f"🗑️ 手动GC: 清理了 {collected} 个对象 (帧#{self.vr_manager.frame_count})") def enable_gc_control(self): """启用垃圾回收控制 - 减少VR渲染期间的GC峰值""" if not self._gc_control_enabled: self._gc_control_enabled = True if not self._gc_disabled: gc.disable() self._gc_disabled = True print("✅ VR垃圾回收控制已启用") else: print("ℹ️ VR垃圾回收控制已经启用") def disable_gc_control(self): """禁用垃圾回收控制 - 恢复自动垃圾回收""" if self._gc_control_enabled: self._gc_control_enabled = False if self._gc_disabled: gc.enable() self._gc_disabled = False print("✅ VR垃圾回收控制已禁用,恢复自动垃圾回收") else: print("ℹ️ VR垃圾回收控制已经禁用") def set_manual_gc_interval(self, frames): """设置手动垃圾回收间隔 Args: frames: 帧数间隔 (建议100-600) """ if 50 <= frames <= 1800: old_interval = self._manual_gc_interval self._manual_gc_interval = frames print(f"✅ 手动GC间隔: {old_interval} → {frames} 帧") else: print("⚠️ GC间隔应在50-1800帧之间") def force_manual_gc(self): """强制执行一次垃圾回收""" collected = gc.collect() print(f"🗑️ 强制GC: 清理了 {collected} 个对象") return collected def get_object_pool_status(self): """获取对象池状态""" return { 'matrix_pool_size': len(self._matrix_pool), 'matrix_pool_capacity': self._matrix_pool_size, 'cached_controllers': len(self.vr_manager.controller_poses), 'cached_matrices': len(self._cached_matrices), } # ====== VR分辨率缩放和质量预设系统 ====== def set_resolution_scale(self, scale): """设置VR分辨率缩放系数 Args: scale: 缩放系数 (0.3-1.0),0.75表示75%分辨率 """ if not (0.3 <= scale <= 1.0): print(f"⚠️ 分辨率缩放系数应在0.3-1.0之间,当前: {scale}") return False old_scale = self.resolution_scale self.resolution_scale = scale # 如果VR已初始化,重新创建缓冲区 if self.vr_manager.vr_initialized: self._apply_resolution_scale() print(f"✓ VR分辨率缩放: {old_scale} → {scale}") pixel_reduction = (1 - scale**2) * 100 print(f"📊 像素减少: {pixel_reduction:.1f}%") return True def set_quality_preset(self, preset_name): """设置VR质量预设 Args: preset_name: 'performance', 'balanced', 'quality' """ if preset_name not in self.quality_presets: print(f"⚠️ 未知的质量预设: {preset_name}") print(f" 可用预设: {list(self.quality_presets.keys())}") return False old_preset = self.current_quality_preset self.current_quality_preset = preset_name scale = self.quality_presets[preset_name] print(f"🎯 切换VR质量预设: {old_preset} → {preset_name}") return self.set_resolution_scale(scale) def cycle_quality_preset(self): """循环切换质量预设""" presets = list(self.quality_presets.keys()) current_index = presets.index(self.current_quality_preset) next_index = (current_index + 1) % len(presets) next_preset = presets[next_index] return self.set_quality_preset(next_preset) def _apply_resolution_scale(self): """应用分辨率缩放,重新创建VR缓冲区""" try: # 计算新的分辨率 self.scaled_eye_width = int(self.base_eye_width * self.resolution_scale) self.scaled_eye_height = int(self.base_eye_height * self.resolution_scale) # 更新当前分辨率 self.vr_manager.eye_width = self.scaled_eye_width self.vr_manager.eye_height = self.scaled_eye_height if hasattr(self.vr_manager, 'current_eye_resolution'): self.vr_manager.current_eye_resolution = (self.vr_manager.eye_width, self.vr_manager.eye_height) print(f"🔄 重新创建VR缓冲区...") print(f" 新分辨率: {self.vr_manager.eye_width}x{self.vr_manager.eye_height}") # 清理旧的缓冲区 self.vr_manager._cleanup_vr_buffers() # 🔧 关键修复:根据渲染模式选择创建方法 success = False if self.vr_manager.vr_render_mode.name == "RENDER_PIPELINE": print(f" 使用RenderPipeline模式重建...") success = self.vr_manager._create_vr_buffers_with_pipeline() if not success: print("⚠️ RenderPipeline模式创建失败,回退到普通渲染模式") self.vr_manager.vr_render_mode = self.vr_manager.VRRenderMode.NORMAL success = self.vr_manager._create_vr_buffers() else: print(f" 使用普通模式重建...") success = self.vr_manager._create_vr_buffers() if success: # 重新设置相机 self.vr_manager._setup_vr_cameras() print("✅ VR缓冲区重新创建成功") return True else: print("❌ VR缓冲区重新创建失败") return False except Exception as e: print(f"❌ 应用分辨率缩放失败: {e}") import traceback traceback.print_exc() return False def get_resolution_info(self): """获取分辨率相关信息""" return { 'base_resolution': (self.base_eye_width, self.base_eye_height), 'current_resolution': (self.vr_manager.eye_width, self.vr_manager.eye_height), 'resolution_scale': self.resolution_scale, 'current_preset': self.current_quality_preset, 'available_presets': self.quality_presets, 'pixel_reduction_percent': (1 - self.resolution_scale**2) * 100 } def print_resolution_info(self): """输出分辨率信息""" info = self.get_resolution_info() print("🔧 ===== VR分辨率信息 =====") print(f" 推荐分辨率: {info['base_resolution'][0]}x{info['base_resolution'][1]}") print(f" 当前分辨率: {info['current_resolution'][0]}x{info['current_resolution'][1]}") print(f" 缩放系数: {info['resolution_scale']}") print(f" 当前预设: {info['current_preset']}") print(f" 像素减少: {info['pixel_reduction_percent']:.1f}%") print(" 可用预设:") for name, scale in info['available_presets'].items(): marker = "✓" if name == info['current_preset'] else " " print(f" {marker} {name}: {scale} ({scale*100:.0f}%)") print("==========================") # ====== 性能模式控制方法 ====== def enable_performance_mode(self): """手动启用性能模式 - 立即禁用详细监控以提升性能""" if not self.performance_mode_enabled: self.performance_mode_enabled = True print("🎯 性能模式已手动启用 - 禁用详细监控以提升性能") print(" 现在将减少每帧对象创建,显著提升VR性能稳定性") else: print("ℹ️ 性能模式已经启用") def disable_performance_mode(self): """禁用性能模式 - 重新启用详细监控(用于调试)""" if self.performance_mode_enabled: self.performance_mode_enabled = False print("🔍 性能模式已禁用 - 重新启用详细监控") print(" 注意:这将增加每帧对象创建,可能影响VR性能") else: print("ℹ️ 性能模式已经禁用") def set_performance_mode_trigger_frame(self, frame_count): """设置性能模式自动触发的帧数 Args: frame_count: 触发帧数 (建议300-1200) """ if 100 <= frame_count <= 3600: old_trigger = self.performance_mode_trigger_frame self.performance_mode_trigger_frame = frame_count print(f"✅ 性能模式触发帧数: {old_trigger} → {frame_count}") else: print("⚠️ 触发帧数应在100-3600之间") def get_performance_mode_status(self): """获取性能模式状态""" return { 'performance_mode_enabled': self.performance_mode_enabled, 'trigger_frame': self.performance_mode_trigger_frame, 'current_frame': self.vr_manager.frame_count, 'will_trigger_at_frame': self.performance_mode_trigger_frame if not self.performance_mode_enabled else None, 'gc_interval_normal': self._manual_gc_interval, 'gc_interval_performance': self._manual_gc_interval * 2, }