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