Source code for simvx.graphics.gpu.instance

"""VkInstance creation, debug messenger, and surface helpers."""


from __future__ import annotations

import logging
from typing import Any

import vulkan as vk

__all__ = ["create_instance", "create_debug_messenger"]

log = logging.getLogger(__name__)

_VALIDATION_LAYER = "VK_LAYER_KHRONOS_validation"


def _validation_available() -> bool:
    layers = vk.vkEnumerateInstanceLayerProperties()
    return any(lp.layerName == _VALIDATION_LAYER for lp in layers)


def _debug_callback(severity, _msg_type, callback_data, _user_data):
    raw = callback_data.pMessage
    msg = raw if isinstance(raw, str) else vk.ffi.string(raw).decode("utf-8")
    if severity >= vk.VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
        log.error("Vulkan: %s", msg)
    elif severity >= vk.VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
        log.warning("Vulkan: %s", msg)
    return vk.VK_FALSE


[docs] def create_instance( app_name: str = "SimVX", extensions: list[str] | None = None, validation: bool = True, ) -> tuple[Any, bool]: """Create a VkInstance with optional validation layers. Returns (instance, validation_enabled). """ extensions = list(extensions or []) layers: list[str] = [] use_validation = validation and _validation_available() if use_validation: layers.append(_VALIDATION_LAYER) if vk.VK_EXT_DEBUG_UTILS_EXTENSION_NAME not in extensions: extensions.append(vk.VK_EXT_DEBUG_UTILS_EXTENSION_NAME) elif validation: log.warning("Validation layers requested but not available — skipping") app_info = vk.VkApplicationInfo( pApplicationName=app_name, applicationVersion=vk.VK_MAKE_VERSION(0, 1, 0), pEngineName="SimVX", engineVersion=vk.VK_MAKE_VERSION(0, 1, 0), apiVersion=vk.VK_MAKE_VERSION(1, 2, 0), ) create_info = vk.VkInstanceCreateInfo( pApplicationInfo=app_info, enabledLayerCount=len(layers), ppEnabledLayerNames=layers, enabledExtensionCount=len(extensions), ppEnabledExtensionNames=extensions, ) instance = vk.vkCreateInstance(create_info, None) log.debug("VkInstance created (validation=%s)", use_validation) return instance, use_validation
[docs] def create_debug_messenger(instance: Any) -> Any: """Attach a debug utils messenger to *instance*.""" create_info = vk.VkDebugUtilsMessengerCreateInfoEXT( messageSeverity=( vk.VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | vk.VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT ), messageType=( vk.VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | vk.VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | vk.VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT ), pfnUserCallback=_debug_callback, ) fn = vk.vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT") if fn is None: log.warning("vkCreateDebugUtilsMessengerEXT not available") return None messenger = fn(instance, create_info, None) log.debug("Debug messenger created") return messenger