meltygui 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- meltygui/__init__.py +107 -0
- meltygui/accounts/__init__.py +0 -0
- meltygui/accounts/internet_accounts.py +1355 -0
- meltygui/chat/__init__.py +91 -0
- meltygui/chat/activity.py +75 -0
- meltygui/chat/backends.py +36 -0
- meltygui/chat/chat_interface.py +732 -0
- meltygui/chat/chat_proxy.py +352 -0
- meltygui/chat/codex_proxy.py +592 -0
- meltygui/chat/codex_settings.py +100 -0
- meltygui/chat/codex_transport.py +60 -0
- meltygui/chat/command_parser.py +204 -0
- meltygui/chat/images.py +227 -0
- meltygui/chat/messages.py +417 -0
- meltygui/chat/metadata.py +139 -0
- meltygui/chat/writer_locks.py +64 -0
- meltygui/code/__init__.py +0 -0
- meltygui/code/basic_converters.py +533 -0
- meltygui/code/chain_converters.py +2111 -0
- meltygui/code/code_checks.py +2209 -0
- meltygui/code/core_syntax.py +1430 -0
- meltygui/code/file_converters.py +1933 -0
- meltygui/code/fileref.py +702 -0
- meltygui/code/hotswap_guard.py +144 -0
- meltygui/code/libcst_conversion.py +9724 -0
- meltygui/code/live_instrument.py +392 -0
- meltygui/code/live_view.py +2490 -0
- meltygui/code/melty_scan.py +2684 -0
- meltygui/code/new_codecs.py +1255 -0
- meltygui/code/new_converters.py +3017 -0
- meltygui/code/project_code.py +278 -0
- meltygui/code/source_context.py +63 -0
- meltygui/code/symbol_roster.py +1588 -0
- meltygui/code/syntax_check.py +34 -0
- meltygui/code/syntax_check_worker.py +114 -0
- meltygui/completion/__init__.py +0 -0
- meltygui/completion/fim.py +1232 -0
- meltygui/completion/fim_context.py +481 -0
- meltygui/completion/providers/__init__.py +0 -0
- meltygui/completion/providers/anthropic_oauth.py +446 -0
- meltygui/completion/providers/anthropic_requests.py +69 -0
- meltygui/completion/providers/claude.py +203 -0
- meltygui/completion/providers/claude_usage.py +499 -0
- meltygui/completion/providers/codex_accounts.py +180 -0
- meltygui/completion/providers/copilot.py +617 -0
- meltygui/completion/providers/oauth_popup.py +220 -0
- meltygui/completion/providers/ollama.py +320 -0
- meltygui/completion/providers/profiles.py +23 -0
- meltygui/core/README.md +88 -0
- meltygui/core/__init__.py +1 -0
- meltygui/core/automation/__init__.py +1 -0
- meltygui/core/automation/action_core.py +153 -0
- meltygui/core/automation/collection_action.py +45 -0
- meltygui/core/automation/mcp_eval.py +167 -0
- meltygui/core/automation/mcp_hotswap.py +107 -0
- meltygui/core/automation/mcp_query.py +552 -0
- meltygui/core/automation/mcp_server.py +657 -0
- meltygui/core/automation/orchestration_core.py +2636 -0
- meltygui/core/automation/query_core.py +124 -0
- meltygui/core/automation/search_core.py +26 -0
- meltygui/core/automation/selector_core.py +340 -0
- meltygui/core/automation/value_core.py +1752 -0
- meltygui/core/cache/__init__.py +1 -0
- meltygui/core/cache/cache_diagnostics.py +0 -0
- meltygui/core/cache/invalidation_decoration.py +153 -0
- meltygui/core/cache/invalidation_tracker.py +43 -0
- meltygui/core/cache/tile_cache.py +5968 -0
- meltygui/core/conversion/__init__.py +1 -0
- meltygui/core/conversion/bubbling.py +599 -0
- meltygui/core/conversion/cache_tree.py +188 -0
- meltygui/core/conversion/chain.py +113 -0
- meltygui/core/conversion/converter_register.py +145 -0
- meltygui/core/conversion/data_decoration.py +67 -0
- meltygui/core/conversion/dict_conversion.py +1815 -0
- meltygui/core/conversion/dict_conversion_util.py +177 -0
- meltygui/core/conversion/dynamic_obj.py +89 -0
- meltygui/core/conversion/graph_compare.py +183 -0
- meltygui/core/conversion/load_save_v2.py +1032 -0
- meltygui/core/conversion/missing_saved_class.py +39 -0
- meltygui/core/conversion/path_finder.py +606 -0
- meltygui/core/conversion/render_host.py +1083 -0
- meltygui/core/core_render.py +6537 -0
- meltygui/core/definition_hotswap.py +231 -0
- meltygui/core/diagnostics/__init__.py +1 -0
- meltygui/core/diagnostics/attribute_churn.py +38 -0
- meltygui/core/diagnostics/fps_counter.py +39 -0
- meltygui/core/diagnostics/gpu_frame_timer.py +103 -0
- meltygui/core/diagnostics/inspection_core.py +169 -0
- meltygui/core/diagnostics/monitor_core.py +105 -0
- meltygui/core/diagnostics/notifications.py +706 -0
- meltygui/core/diagnostics/perf_trace.py +281 -0
- meltygui/core/diagnostics/profile_decoration.py +88 -0
- meltygui/core/diagnostics/resize_trace.py +62 -0
- meltygui/core/diagnostics/screenshot_core.py +247 -0
- meltygui/core/diagnostics/session_status.py +98 -0
- meltygui/core/diagnostics/trace_core.py +445 -0
- meltygui/core/files/__init__.py +1 -0
- meltygui/core/files/file_core.py +208 -0
- meltygui/core/files/file_explorer_core.py +104 -0
- meltygui/core/files/file_tree_core.py +198 -0
- meltygui/core/files/file_watch_core.py +43 -0
- meltygui/core/files/import_graph_core.py +43 -0
- meltygui/core/files/metadata_core.py +51 -0
- meltygui/core/graphics/__init__.py +1 -0
- meltygui/core/graphics/cuda_context_core.py +166 -0
- meltygui/core/graphics/cuda_interop_core.py +136 -0
- meltygui/core/graphics/cuda_kernel_core.py +91 -0
- meltygui/core/graphics/framebuffer_recorder.py +337 -0
- meltygui/core/graphics/gl_state.py +658 -0
- meltygui/core/graphics/lut_core.py +52 -0
- meltygui/core/graphics/overlay_renderer.py +984 -0
- meltygui/core/graphics/scene_target.py +180 -0
- meltygui/core/graphics/screenshot.py +439 -0
- meltygui/core/graphics/shader_func.py +478 -0
- meltygui/core/graphics/tensor_core.py +45 -0
- meltygui/core/graphics/text_texture.py +329 -0
- meltygui/core/graphics/wayland_color.py +635 -0
- meltygui/core/input/__init__.py +1 -0
- meltygui/core/input/collision.py +165 -0
- meltygui/core/input/drag_drop_core.py +1525 -0
- meltygui/core/input/hypr_left_drag.py +323 -0
- meltygui/core/input/input_core.py +245 -0
- meltygui/core/input/input_handler.py +1101 -0
- meltygui/core/input/mouse_cursor.py +355 -0
- meltygui/core/input/pynput_backend.py +1054 -0
- meltygui/core/input/space_mouse.py +338 -0
- meltygui/core/input/touchpad_backend.py +393 -0
- meltygui/core/input/view_selection.py +177 -0
- meltygui/core/layout/__init__.py +1 -0
- meltygui/core/layout/column_core.py +2153 -0
- meltygui/core/layout/cursor_core.py +161 -0
- meltygui/core/layout/dropdown_core.py +278 -0
- meltygui/core/layout/edge_constraints.py +155 -0
- meltygui/core/layout/grid_core.py +117 -0
- meltygui/core/layout/header_core.py +23 -0
- meltygui/core/layout/header_runtime.py +67 -0
- meltygui/core/layout/layout_core.py +87 -0
- meltygui/core/layout/tile_manager_core.py +591 -0
- meltygui/core/melty.py +6726 -0
- meltygui/core/module_map.json +896 -0
- meltygui/core/module_names.py +19 -0
- meltygui/core/rendering/__init__.py +1 -0
- meltygui/core/rendering/core_decoration.py +431 -0
- meltygui/core/rendering/core_render_helpers.py +328 -0
- meltygui/core/rendering/func_metadata.py +398 -0
- meltygui/core/rendering/mode.py +818 -0
- meltygui/core/rendering/mode_defaults.py +41 -0
- meltygui/core/rendering/modes.py +136 -0
- meltygui/core/rendering/parameter_core.py +1665 -0
- meltygui/core/rendering/render_dispatch.py +1891 -0
- meltygui/core/rendering/render_funcs.py +273 -0
- meltygui/core/rendering/shaped.py +312 -0
- meltygui/core/rendering/window_decoration.py +25 -0
- meltygui/core/runtime/__init__.py +1 -0
- meltygui/core/runtime/app.py +735 -0
- meltygui/core/runtime/app_session.py +140 -0
- meltygui/core/runtime/background.py +564 -0
- meltygui/core/runtime/extensions.py +53 -0
- meltygui/core/runtime/gc_manager.py +1163 -0
- meltygui/core/runtime/lifecycle.py +21 -0
- meltygui/core/runtime/paths.py +27 -0
- meltygui/core/runtime/settings.py +14 -0
- meltygui/core/runtime/singleton.py +16 -0
- meltygui/core/runtime/thread_safe_bool.py +24 -0
- meltygui/core/runtime/thread_signal.py +30 -0
- meltygui/core/runtime/toggles.py +3115 -0
- meltygui/core/services/__init__.py +1 -0
- meltygui/core/services/account_core.py +10 -0
- meltygui/core/services/chat_core.py +19 -0
- meltygui/core/services/claude_terminal_core.py +346 -0
- meltygui/core/services/terminal_core.py +458 -0
- meltygui/core/services/terminal_runtime.py +78 -0
- meltygui/core/styling/__init__.py +1 -0
- meltygui/core/styling/color_core.py +46 -0
- meltygui/core/styling/fonts.py +639 -0
- meltygui/core/styling/global_style.py +338 -0
- meltygui/core/styling/style.py +198 -0
- meltygui/core/styling/style_core.py +522 -0
- meltygui/core/styling/warm_start.py +149 -0
- meltygui/core/windowing/__init__.py +1 -0
- meltygui/core/windowing/backends/PYIMGUI_LICENSE +28 -0
- meltygui/core/windowing/backends/__init__.py +1 -0
- meltygui/core/windowing/backends/imgui_renderer.py +138 -0
- meltygui/core/windowing/backends/native_wayland.py +850 -0
- meltygui/core/windowing/backends/protocols/xdg-decoration-unstable-v1.xml +156 -0
- meltygui/core/windowing/backends/protocols/xdg-shell.xml +1420 -0
- meltygui/core/windowing/backends/wayland_protocol.py +101 -0
- meltygui/core/windowing/dock_core.py +182 -0
- meltygui/core/windowing/frame_geometry.py +42 -0
- meltygui/core/windowing/geometry_feed.py +864 -0
- meltygui/core/windowing/glfw_utils.py +1343 -0
- meltygui/core/windowing/os_frame.py +1552 -0
- meltygui/core/windowing/surface.py +643 -0
- meltygui/core/windowing/titlebar.py +1560 -0
- meltygui/core/windowing/titlebar_buttons.py +281 -0
- meltygui/core/windowing/wayland_move.py +932 -0
- meltygui/core/windowing/window_api.py +62 -0
- meltygui/core/windowing/window_constants.py +339 -0
- meltygui/core/windowing/window_visibility.py +162 -0
- meltygui/debug/__init__.py +0 -0
- meltygui/debug/app_view_utils.py +9 -0
- meltygui/editor/__init__.py +0 -0
- meltygui/editor/bash_syntax.py +30 -0
- meltygui/editor/code_line_fast.py +152 -0
- meltygui/editor/diff.py +139 -0
- meltygui/editor/external_changes.py +159 -0
- meltygui/editor/file_header.py +41 -0
- meltygui/editor/live_usage.py +169 -0
- meltygui/editor/live_view_views.py +1803 -0
- meltygui/editor/pending_save.py +1351 -0
- meltygui/editor/roster_tints.py +547 -0
- meltygui/editor/source_preview.py +16 -0
- meltygui/editor/source_tools.py +10 -0
- meltygui/editor/source_ui.py +70 -0
- meltygui/editor/spell_check.py +77 -0
- meltygui/editor/text_editor.py +9076 -0
- meltygui/editor/usage_picker.py +538 -0
- meltygui/events/__init__.py +0 -0
- meltygui/events/example.py +118 -0
- meltygui/examples/__init__.py +0 -0
- meltygui/examples/columns_demo.py +33 -0
- meltygui/examples/columns_window_demo.py +60 -0
- meltygui/examples/context_menu_demo.py +24 -0
- meltygui/examples/context_menu_window_demo.py +49 -0
- meltygui/examples/gui_playground.py +127 -0
- meltygui/examples/live_view_playground.py +256 -0
- meltygui/examples/lora.py +43 -0
- meltygui/examples/lora_data.py +59 -0
- meltygui/examples/lora_policies.py +67 -0
- meltygui/examples/mode_demo.py +49 -0
- meltygui/examples/modifies_demo.py +119 -0
- meltygui/examples/scalar_policies.py +60 -0
- meltygui/examples/style_layouts.py +149 -0
- meltygui/examples/tile_manager_demo.py +74 -0
- meltygui/examples/tint_demo.py +160 -0
- meltygui/examples/tint_functions.py +56 -0
- meltygui/examples/trace_demo.py +88 -0
- meltygui/examples/two_windows.py +36 -0
- meltygui/files/__init__.py +0 -0
- meltygui/files/fast_file_explorer.py +439 -0
- meltygui/gnome_extension/lsd-window-geometry@latent-descent/extension.js +237 -0
- meltygui/gnome_extension/lsd-window-geometry@latent-descent/lsd-window-geometry@latent-descent.iml +9 -0
- meltygui/gnome_extension/lsd-window-geometry@latent-descent/metadata.json +7 -0
- meltygui/graphics/__init__.py +6 -0
- meltygui/graphics/base.py +85 -0
- meltygui/graphics/examples.py +507 -0
- meltygui/graphics/executor.py +520 -0
- meltygui/graphics/filter.py +667 -0
- meltygui/graphics/filter.pyi +856 -0
- meltygui/graphics/generate_stubs.py +22 -0
- meltygui/graphics/registry.py +203 -0
- meltygui/graphics/shader_compiler.py +155 -0
- meltygui/graphics/shaders.py +1302 -0
- meltygui/graphics/stub_generator.py +250 -0
- meltygui/graphics/texture_manager.py +170 -0
- meltygui/graphics/texture_min_max.py +295 -0
- meltygui/hdr_color.py +757 -0
- meltygui/image_load.py +308 -0
- meltygui/model/__init__.py +1 -0
- meltygui/model/account_model.py +142 -0
- meltygui/model/camera_model.py +159 -0
- meltygui/model/chat_model.py +86 -0
- meltygui/model/code_model.py +62 -0
- meltygui/model/code_proxy_model.py +876 -0
- meltygui/model/collection_model.py +41 -0
- meltygui/model/color_model.py +127 -0
- meltygui/model/cuda_tensor_model.py +36 -0
- meltygui/model/cuda_texture_model.py +149 -0
- meltygui/model/dropdown_model.py +137 -0
- meltygui/model/file_metadata_model.py +73 -0
- meltygui/model/file_model.py +289 -0
- meltygui/model/format_model.py +390 -0
- meltygui/model/graph_model.py +98 -0
- meltygui/model/icon_model.py +1024 -0
- meltygui/model/import_graph_model.py +468 -0
- meltygui/model/layout_model.py +15 -0
- meltygui/model/lut_model.py +266 -0
- meltygui/model/search_model.py +173 -0
- meltygui/model/tensor_model.py +402 -0
- meltygui/model/terminal_model.py +329 -0
- meltygui/model/texture_model.py +146 -0
- meltygui/model/tile_model.py +24 -0
- meltygui/model/trace_model.py +198 -0
- meltygui/model/trace_report_model.py +146 -0
- meltygui/models/__init__.py +0 -0
- meltygui/models/file_meta.py +613 -0
- meltygui/models/function_console.py +184 -0
- meltygui/models/orchestration.py +48 -0
- meltygui/pbr.py +1576 -0
- meltygui/png_unfilter.c +49 -0
- meltygui/resources/JetBrainsMono-Regular.ttf +0 -0
- meltygui/resources/THIRD_PARTY_NOTICES.md +21 -0
- meltygui/resources/dejavu/DejaVuSans-Bold.ttf +0 -0
- meltygui/resources/dejavu/DejaVuSans-ExtraLight.ttf +0 -0
- meltygui/resources/dejavu/DejaVuSans.ttf +0 -0
- meltygui/resources/dejavu/LICENSE.txt +78 -0
- meltygui/resources/fontawesome-LICENSE.txt +121 -0
- meltygui/resources/fontawesome-webfont.ttf +0 -0
- meltygui/resources/hdri/studio_small_09_1k.hdr +0 -0
- meltygui/resources/jetbrains-weights/JetBrainsMono-Bold.ttf +0 -0
- meltygui/resources/jetbrains-weights/JetBrainsMono-ExtraBold.ttf +0 -0
- meltygui/resources/jetbrains-weights/JetBrainsMono-ExtraLight.ttf +0 -0
- meltygui/resources/jetbrains-weights/JetBrainsMono-Light.ttf +0 -0
- meltygui/resources/jetbrains-weights/JetBrainsMono-Medium.ttf +0 -0
- meltygui/resources/jetbrains-weights/JetBrainsMono-SemiBold.ttf +0 -0
- meltygui/resources/jetbrains-weights/JetBrainsMono-Thin.ttf +0 -0
- meltygui/resources/jetbrains-weights/OFL.txt +93 -0
- meltygui/resources/jetbrains-weights/README.md +2 -0
- meltygui/state/__init__.py +0 -0
- meltygui/state/account_state.py +22 -0
- meltygui/state/animation_state.py +97 -0
- meltygui/state/annotation_state.py +22 -0
- meltygui/state/chat_state.py +36 -0
- meltygui/state/code_state.py +10 -0
- meltygui/state/core_enums.py +59 -0
- meltygui/state/core_markers.py +115 -0
- meltygui/state/core_undo.py +1075 -0
- meltygui/state/file_state.py +75 -0
- meltygui/state/graph_state.py +26 -0
- meltygui/state/inspection_state.py +47 -0
- meltygui/state/menu_state.py +10 -0
- meltygui/state/model_enums.py +11 -0
- meltygui/state/new_core_model.py +2394 -0
- meltygui/state/orchestration_state.py +14 -0
- meltygui/state/query_state.py +24 -0
- meltygui/state/tensor_state.py +10 -0
- meltygui/state/terminal_state.py +23 -0
- meltygui/state/trace_state.py +32 -0
- meltygui/state/voxel_state.py +12 -0
- meltygui/text_index.py +816 -0
- meltygui/utils/__init__.py +0 -0
- meltygui/utils/jump_to_code.py +344 -0
- meltygui/utils/pkl_inspect.py +90 -0
- meltygui/utils/render_utils.py +1419 -0
- meltygui/view/__init__.py +1 -0
- meltygui/view/account_view.py +524 -0
- meltygui/view/action_view.py +73 -0
- meltygui/view/chat_decoration_view.py +112 -0
- meltygui/view/chat_view.py +1703 -0
- meltygui/view/code_view.py +2677 -0
- meltygui/view/collection_view.py +1185 -0
- meltygui/view/color_view.py +824 -0
- meltygui/view/control_view.py +559 -0
- meltygui/view/decoration_view.py +439 -0
- meltygui/view/diagnostic_view.py +177 -0
- meltygui/view/dropdown_view.py +1082 -0
- meltygui/view/file_view.py +1599 -0
- meltygui/view/graph_cuda_view.py +105 -0
- meltygui/view/graph_view.py +882 -0
- meltygui/view/header_view.py +848 -0
- meltygui/view/input_view.py +238 -0
- meltygui/view/inspection_view.py +1783 -0
- meltygui/view/layout_view.py +596 -0
- meltygui/view/lut_view.py +45 -0
- meltygui/view/menu_view.py +212 -0
- meltygui/view/orchestration_view.py +658 -0
- meltygui/view/query_view.py +118 -0
- meltygui/view/search_view.py +342 -0
- meltygui/view/tab_view.py +258 -0
- meltygui/view/tensor_view.py +430 -0
- meltygui/view/terminal_view.py +355 -0
- meltygui/view/text_view.py +8031 -0
- meltygui/view/texture_view.py +480 -0
- meltygui/view/tile_view.py +38 -0
- meltygui/view/trace_view.py +923 -0
- meltygui/view/voxel_cuda_view.py +824 -0
- meltygui/view/voxel_view.py +1860 -0
- meltygui/view/window_view.py +111 -0
- meltygui-0.1.0.dist-info/METADATA +143 -0
- meltygui-0.1.0.dist-info/RECORD +372 -0
- meltygui-0.1.0.dist-info/WHEEL +4 -0
- meltygui-0.1.0.dist-info/licenses/LICENSE +202 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"""Shared CUDA context ownership for rendering and GL interop.
|
|
2
|
+
|
|
3
|
+
Per-device kernel leases live as long as compiled kernels; the standalone display
|
|
4
|
+
stack entry has a separate lease so popping it cannot invalidate cached kernels.
|
|
5
|
+
Both use CUDA primary contexts, so Torch storage remains directly accessible.
|
|
6
|
+
"""
|
|
7
|
+
import atexit
|
|
8
|
+
from contextlib import contextmanager
|
|
9
|
+
import ctypes
|
|
10
|
+
import sys
|
|
11
|
+
import threading
|
|
12
|
+
|
|
13
|
+
from meltygui.core.melty import Melty
|
|
14
|
+
from meltygui.core.graphics.gl_state import is_gl_thread
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class CudaContextRuntime:
|
|
18
|
+
def __init__(self):
|
|
19
|
+
self.contexts = {}
|
|
20
|
+
self.kernels = {}
|
|
21
|
+
self.legacy_kernels = None
|
|
22
|
+
self.primary_context = None
|
|
23
|
+
self.primary_thread = None
|
|
24
|
+
self.last_logged = None
|
|
25
|
+
self.driver_library = None
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def runtime():
|
|
29
|
+
if Melty.cuda_interop is None:
|
|
30
|
+
Melty.cuda_interop = CudaContextRuntime()
|
|
31
|
+
state = Melty.cuda_interop
|
|
32
|
+
# Transfer the old cache's context leases without reacquiring resources.
|
|
33
|
+
# Existing interop runtime objects gain the pool on first use after hotswap.
|
|
34
|
+
if 'contexts' not in state.__dict__:
|
|
35
|
+
state.contexts = {}
|
|
36
|
+
state.contexts.update(sys.__dict__.pop('_lsd_cuda_march_contexts', {}))
|
|
37
|
+
return state
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def primary_context_for(device):
|
|
41
|
+
"""Retain a render-thread primary context for compiled kernels on a device."""
|
|
42
|
+
if not is_gl_thread():
|
|
43
|
+
raise RuntimeError('rendering CUDA contexts belong to the render thread')
|
|
44
|
+
device = int(device)
|
|
45
|
+
contexts = runtime().contexts
|
|
46
|
+
if device not in contexts:
|
|
47
|
+
import meltygui_pycuda.driver as cuda
|
|
48
|
+
cuda.init()
|
|
49
|
+
contexts[device] = cuda.Device(device).retain_primary_context()
|
|
50
|
+
return contexts[device]
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@contextmanager
|
|
54
|
+
def using_device(device):
|
|
55
|
+
"""Run on a tensor's GPU and restore PyCUDA and native caller contexts."""
|
|
56
|
+
with using_context(primary_context_for(device)):
|
|
57
|
+
yield
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def ensure_primary_context(device):
|
|
61
|
+
"""Install the standalone render-thread stack entry when none exists."""
|
|
62
|
+
if not is_gl_thread():
|
|
63
|
+
return False
|
|
64
|
+
import meltygui_pycuda.driver as cuda
|
|
65
|
+
cuda.init()
|
|
66
|
+
state = runtime()
|
|
67
|
+
if cuda.Context.get_current() is not None or state.primary_context is not None:
|
|
68
|
+
return False
|
|
69
|
+
context = cuda.Device(int(device)).retain_primary_context()
|
|
70
|
+
try:
|
|
71
|
+
context.push()
|
|
72
|
+
except Exception:
|
|
73
|
+
detach_inactive_primary(context)
|
|
74
|
+
raise
|
|
75
|
+
state.primary_context = context
|
|
76
|
+
state.primary_thread = threading.current_thread()
|
|
77
|
+
atexit.register(_detach_primary)
|
|
78
|
+
return True
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _driver_library():
|
|
82
|
+
state = runtime()
|
|
83
|
+
if state.driver_library is None:
|
|
84
|
+
library = ctypes.CDLL('libcuda.so.1')
|
|
85
|
+
query = library.cuGLGetDevices_v2
|
|
86
|
+
query.argtypes = (ctypes.POINTER(ctypes.c_uint), ctypes.POINTER(ctypes.c_int),
|
|
87
|
+
ctypes.c_uint, ctypes.c_uint)
|
|
88
|
+
query.restype = ctypes.c_int
|
|
89
|
+
for name in ('cuCtxGetCurrent', 'cuCtxPopCurrent_v2'):
|
|
90
|
+
function = getattr(library, name)
|
|
91
|
+
function.argtypes = (ctypes.POINTER(ctypes.c_void_p),)
|
|
92
|
+
function.restype = ctypes.c_int
|
|
93
|
+
library.cuCtxSetCurrent.argtypes = (ctypes.c_void_p,)
|
|
94
|
+
library.cuCtxSetCurrent.restype = ctypes.c_int
|
|
95
|
+
state.driver_library = library
|
|
96
|
+
return state.driver_library
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _native_context():
|
|
100
|
+
context = ctypes.c_void_p()
|
|
101
|
+
result = _driver_library().cuCtxGetCurrent(ctypes.byref(context))
|
|
102
|
+
if result != 0:
|
|
103
|
+
raise RuntimeError(f"cuCtxGetCurrent failed: {result}")
|
|
104
|
+
return context.value
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def current_device_index():
|
|
108
|
+
"""The CUDA ordinal of the context current on this thread, or None."""
|
|
109
|
+
import meltygui_pycuda.driver as cuda
|
|
110
|
+
if cuda.Context.get_current() is None:
|
|
111
|
+
return None
|
|
112
|
+
bus = cuda.Context.get_device().pci_bus_id()
|
|
113
|
+
for index in range(cuda.Device.count()):
|
|
114
|
+
if cuda.Device(index).pci_bus_id() == bus:
|
|
115
|
+
return index
|
|
116
|
+
return None
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def _detach_primary():
|
|
120
|
+
state = runtime()
|
|
121
|
+
if state.primary_context is None:
|
|
122
|
+
return
|
|
123
|
+
import meltygui_pycuda.driver as cuda
|
|
124
|
+
if (threading.current_thread() is not state.primary_thread
|
|
125
|
+
or cuda.Context.get_current() != state.primary_context):
|
|
126
|
+
# Popping someone else's stack entry corrupts its owner's lifetime.
|
|
127
|
+
return
|
|
128
|
+
cuda.Context.pop()
|
|
129
|
+
detach_inactive_primary(state.primary_context)
|
|
130
|
+
state.primary_context = None
|
|
131
|
+
state.primary_thread = None
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def detach_inactive_primary(context):
|
|
135
|
+
"""Release an owned primary-context lease AFTER removing its PyCUDA entry.
|
|
136
|
+
|
|
137
|
+
PyCUDA's inactive-context detach pushes the native context and assumes that
|
|
138
|
+
releasing it also pops it. cuDevicePrimaryCtxRelease explicitly does not pop
|
|
139
|
+
(cuda.h); balance that native push without touching PyCUDA's restored stack.
|
|
140
|
+
"""
|
|
141
|
+
context.detach()
|
|
142
|
+
popped = ctypes.c_void_p()
|
|
143
|
+
result = _driver_library().cuCtxPopCurrent_v2(ctypes.byref(popped))
|
|
144
|
+
if result != 0:
|
|
145
|
+
raise RuntimeError(f"cuCtxPopCurrent after primary release failed: {result}")
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
@contextmanager
|
|
149
|
+
def using_context(context):
|
|
150
|
+
"""Temporarily restore a registration's CUDA context, preserving the stack."""
|
|
151
|
+
import meltygui_pycuda.driver as cuda
|
|
152
|
+
previous_native = _native_context()
|
|
153
|
+
pushed = cuda.Context.get_current() != context or previous_native != context.handle
|
|
154
|
+
if pushed:
|
|
155
|
+
context.push()
|
|
156
|
+
try:
|
|
157
|
+
yield
|
|
158
|
+
finally:
|
|
159
|
+
if pushed:
|
|
160
|
+
cuda.Context.pop()
|
|
161
|
+
# Torch may also switch the native context inside an already-current
|
|
162
|
+
# scope, where no PyCUDA push/pop was needed on entry.
|
|
163
|
+
if _native_context() != previous_native:
|
|
164
|
+
result = _driver_library().cuCtxSetCurrent(previous_native)
|
|
165
|
+
if result != 0:
|
|
166
|
+
raise RuntimeError(f"restoring CUDA context failed: {result}")
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"""CUDA context selection and registered-buffer operations for OpenGL interop.
|
|
2
|
+
|
|
3
|
+
The rendering context determines the device. Never register GL resources from an
|
|
4
|
+
unrelated CUDA device, even when Torch's current device happens to be that device.
|
|
5
|
+
Tensor adaptation and texture ownership live in model/cuda_texture_model.py.
|
|
6
|
+
"""
|
|
7
|
+
from contextlib import contextmanager
|
|
8
|
+
import ctypes
|
|
9
|
+
|
|
10
|
+
from meltygui.core.graphics import cuda_context_core
|
|
11
|
+
from meltygui.core.graphics.gl_state import (
|
|
12
|
+
ResourceDeletionDeferred, current_context, is_gl_thread,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def log_once(message):
|
|
17
|
+
state = cuda_context_core.runtime()
|
|
18
|
+
if message != state.last_logged:
|
|
19
|
+
print(f"[cuda_interop] {message}")
|
|
20
|
+
state.last_logged = message
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def gl_devices():
|
|
24
|
+
"""CUDA ordinals associated with the current GL context, or none.
|
|
25
|
+
|
|
26
|
+
PyCUDA does not expose cuGLGetDevices; use the CUDA driver's public API.
|
|
27
|
+
The versioned symbol and enum values are declared in CUDA's cudaGL.h.
|
|
28
|
+
"""
|
|
29
|
+
if not is_gl_thread() or current_context() is None:
|
|
30
|
+
return ()
|
|
31
|
+
import meltygui_pycuda.driver as cuda
|
|
32
|
+
cuda.init()
|
|
33
|
+
capacity = cuda.Device.count()
|
|
34
|
+
devices = (ctypes.c_int * capacity)()
|
|
35
|
+
count = ctypes.c_uint()
|
|
36
|
+
# CU_GL_DEVICE_LIST_ALL: all GPUs used by the current GL context.
|
|
37
|
+
result = cuda_context_core._driver_library().cuGLGetDevices_v2(ctypes.byref(count), devices, capacity, 1)
|
|
38
|
+
if result != 0:
|
|
39
|
+
return ()
|
|
40
|
+
return tuple(devices[:count.value])
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def cuda_ready():
|
|
44
|
+
"""Whether GL interop is safe in the current thread and context pair."""
|
|
45
|
+
if not is_gl_thread() or current_context() is None:
|
|
46
|
+
return False
|
|
47
|
+
try:
|
|
48
|
+
import meltygui_pycuda.driver as cuda
|
|
49
|
+
import meltygui_pycuda.gl
|
|
50
|
+
context = cuda.Context.get_current()
|
|
51
|
+
if context is None or context.handle != cuda_context_core._native_context():
|
|
52
|
+
return False
|
|
53
|
+
device = cuda_context_core.current_device_index()
|
|
54
|
+
return device is not None and device in gl_devices()
|
|
55
|
+
except Exception:
|
|
56
|
+
return False
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def ensure_context():
|
|
60
|
+
"""For standalone/test setup, retain the GL device's primary context.
|
|
61
|
+
|
|
62
|
+
An existing compatible context is left alone. An incompatible one is
|
|
63
|
+
rejected, not silently replaced. Only the context retained here is detached.
|
|
64
|
+
"""
|
|
65
|
+
if not is_gl_thread() or current_context() is None:
|
|
66
|
+
return False
|
|
67
|
+
try:
|
|
68
|
+
import meltygui_pycuda.driver as cuda
|
|
69
|
+
import meltygui_pycuda.gl
|
|
70
|
+
devices = gl_devices()
|
|
71
|
+
if not devices:
|
|
72
|
+
return False
|
|
73
|
+
if cuda.Context.get_current() is not None:
|
|
74
|
+
return cuda_ready()
|
|
75
|
+
return cuda_context_core.ensure_primary_context(devices[0])
|
|
76
|
+
except Exception as error:
|
|
77
|
+
log_once(f"ensure_context failed: {error}")
|
|
78
|
+
return False
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def register_buffer(buffer):
|
|
82
|
+
if not cuda_ready():
|
|
83
|
+
raise RuntimeError("CUDA registration requires a compatible current GL/CUDA context pair")
|
|
84
|
+
from meltygui_pycuda import gl as cuda_gl
|
|
85
|
+
return cuda_gl.RegisteredBuffer(buffer, cuda_gl.graphics_map_flags.WRITE_DISCARD)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@contextmanager
|
|
89
|
+
def interop_context():
|
|
90
|
+
"""Activate a GL-compatible context for one adapter operation.
|
|
91
|
+
|
|
92
|
+
Torch can change the native context while PyCUDA still records the rendering
|
|
93
|
+
context. Reactivate that context locally, validate its GL device, and restore
|
|
94
|
+
the caller's native context afterward. A genuinely incompatible PyCUDA context
|
|
95
|
+
is rejected. Standalone callers with no PyCUDA context get lazy setup.
|
|
96
|
+
"""
|
|
97
|
+
if not is_gl_thread() or current_context() is None:
|
|
98
|
+
yield None
|
|
99
|
+
return
|
|
100
|
+
try:
|
|
101
|
+
import meltygui_pycuda.driver as cuda
|
|
102
|
+
import meltygui_pycuda.gl
|
|
103
|
+
context = cuda.Context.get_current()
|
|
104
|
+
if context is None and ensure_context():
|
|
105
|
+
context = cuda.Context.get_current()
|
|
106
|
+
except Exception:
|
|
107
|
+
context = None
|
|
108
|
+
if context is None:
|
|
109
|
+
yield None
|
|
110
|
+
return
|
|
111
|
+
with cuda_context_core.using_context(context):
|
|
112
|
+
yield context if cuda_ready() else None
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def copy_to_buffer(registered, context, pointer, nbytes):
|
|
116
|
+
"""Copy ready device storage into a mapped GL buffer and unmap on failure."""
|
|
117
|
+
import meltygui_pycuda.driver as cuda
|
|
118
|
+
with cuda_context_core.using_context(context):
|
|
119
|
+
mapping = registered.map()
|
|
120
|
+
try:
|
|
121
|
+
destination, capacity = mapping.device_ptr_and_size()
|
|
122
|
+
if capacity < nbytes:
|
|
123
|
+
raise ValueError(f"CUDA buffer has {capacity} bytes; upload needs {nbytes}")
|
|
124
|
+
cuda.memcpy_dtod(destination, pointer, nbytes)
|
|
125
|
+
cuda.Context.synchronize()
|
|
126
|
+
finally:
|
|
127
|
+
mapping.unmap()
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def unregister_buffer(registered, context):
|
|
131
|
+
try:
|
|
132
|
+
with cuda_context_core.using_context(context):
|
|
133
|
+
registered.unregister()
|
|
134
|
+
except Exception as error:
|
|
135
|
+
log_once(f"unregister deferred: {error}")
|
|
136
|
+
raise ResourceDeletionDeferred from error
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""Render-thread CUDA compilation and process-lifetime kernel ownership.
|
|
2
|
+
|
|
3
|
+
Feature views supply CUDA source and entry points. Melty's CUDA runtime retains
|
|
4
|
+
modules alongside their primary contexts, including across definition hotswaps.
|
|
5
|
+
"""
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
from meltygui.core.graphics.cuda_context_core import runtime, using_device
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def available():
|
|
12
|
+
try:
|
|
13
|
+
import meltygui_pycuda.driver
|
|
14
|
+
import meltygui_pycuda as pycuda # noqa: F401
|
|
15
|
+
return True
|
|
16
|
+
except Exception:
|
|
17
|
+
return False
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def host_compiler_flags():
|
|
21
|
+
"""Use an installed CUDA-12-compatible C++ compiler when available."""
|
|
22
|
+
import shutil
|
|
23
|
+
for version in ("12", "11", "10"):
|
|
24
|
+
if shutil.which("gcc-" + version) and shutil.which("g++-" + version):
|
|
25
|
+
return ["-ccbin", "g++-" + version]
|
|
26
|
+
return ["-allow-unsupported-compiler"]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class CudaKernel:
|
|
30
|
+
def __init__(self, source, module, functions):
|
|
31
|
+
self.source = source
|
|
32
|
+
self.module = module
|
|
33
|
+
self.functions = functions
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _cache():
|
|
37
|
+
state = runtime()
|
|
38
|
+
if 'kernels' not in state.__dict__:
|
|
39
|
+
state.kernels = {}
|
|
40
|
+
# One-time runtime transfer, not import compatibility. Keep existing compiled
|
|
41
|
+
# functions alive until their feature is next requested under its context.
|
|
42
|
+
if 'legacy_kernels' not in state.__dict__ or state.legacy_kernels is None:
|
|
43
|
+
state.legacy_kernels = {
|
|
44
|
+
'voxels': sys.__dict__.pop('_lsd_cuda_march_kernels', {}),
|
|
45
|
+
'lines': sys.__dict__.pop('_melty_cuda_line_kernels', {}),
|
|
46
|
+
}
|
|
47
|
+
return state.kernels
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def kernel_functions(feature, device, source, names):
|
|
51
|
+
"""Compile a feature's entry points once per source/device.
|
|
52
|
+
|
|
53
|
+
A failed replacement leaves the last good module owned by the runtime.
|
|
54
|
+
Replacement and destruction happen with the owning device context active.
|
|
55
|
+
Unchanged source after hotswap retains the same function objects.
|
|
56
|
+
"""
|
|
57
|
+
device = int(device)
|
|
58
|
+
names = tuple(names)
|
|
59
|
+
# This also enforces the render-thread contract on hits and before adopting
|
|
60
|
+
# old entries; none of the runtime dictionaries can be mutated by workers.
|
|
61
|
+
with using_device(device):
|
|
62
|
+
cache = _cache()
|
|
63
|
+
key = (feature, device, names)
|
|
64
|
+
entry = cache.get(key)
|
|
65
|
+
if entry is not None and entry.source == source:
|
|
66
|
+
return entry.functions
|
|
67
|
+
legacy = runtime().legacy_kernels.get(feature, {}).get(device)
|
|
68
|
+
if legacy is not None:
|
|
69
|
+
if feature == 'voxels' and isinstance(legacy, dict) and legacy.get('__source__') == hash(source):
|
|
70
|
+
entry = CudaKernel(source, None, {name: legacy[name] for name in names})
|
|
71
|
+
elif feature == 'lines' and legacy[0] == source:
|
|
72
|
+
entry = CudaKernel(source, legacy[1], dict(zip(names, legacy[2:])))
|
|
73
|
+
if entry is not None and entry.source == source:
|
|
74
|
+
cache[key] = entry
|
|
75
|
+
runtime().legacy_kernels[feature].pop(device)
|
|
76
|
+
return entry.functions
|
|
77
|
+
import meltygui_pycuda.driver as cuda
|
|
78
|
+
from meltygui_pycuda.compiler import SourceModule
|
|
79
|
+
capability = cuda.Device(device).compute_capability()
|
|
80
|
+
module = SourceModule(source, no_extern_c=True, arch='sm_%d%d' % capability,
|
|
81
|
+
options=['-O3'] + host_compiler_flags())
|
|
82
|
+
try:
|
|
83
|
+
functions = {name: module.get_function(name) for name in names}
|
|
84
|
+
except Exception:
|
|
85
|
+
del module
|
|
86
|
+
raise
|
|
87
|
+
cache[key] = CudaKernel(source, module, functions)
|
|
88
|
+
runtime().legacy_kernels.get(feature, {}).pop(device, None)
|
|
89
|
+
# Drop replaced and transferred references while the context is active.
|
|
90
|
+
del entry, legacy
|
|
91
|
+
return functions
|