CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-glfw

A ctypes-based wrapper for GLFW3 that provides Python bindings for OpenGL, OpenGL ES, and Vulkan development on desktop platforms.

Pending
Overview
Eval results
Files

vulkan-support.mddocs/

Vulkan Support

Vulkan surface creation, instance management, and Vulkan function loading for modern low-level graphics programming.

Capabilities

Vulkan Availability

Check for Vulkan support and loader availability.

def vulkan_supported() -> bool:
    """
    Check whether the Vulkan loader has been found.
    
    This function returns whether the Vulkan loader and any minimally 
    functional ICD have been found.
    
    Returns:
        bool: True if Vulkan is supported, False otherwise
    """

Vulkan Extensions

Query required Vulkan instance extensions for presentation support.

def get_required_instance_extensions() -> list[str]:
    """
    Get the Vulkan instance extensions required by GLFW.
    
    This function returns a list of names of Vulkan instance extensions 
    required by GLFW for creating Vulkan surfaces for GLFW windows.
    
    Returns:
        list[str]: List of required extension names
    """

Vulkan Surface Creation

Create Vulkan surfaces for windows to enable Vulkan rendering.

def create_window_surface(instance, window, allocator, surface) -> int:
    """
    Create a Vulkan surface for the specified window.
    
    This function creates a Vulkan surface for the specified window.
    
    Parameters:
        instance: Vulkan instance handle (VkInstance)
        window: Window to create surface for
        allocator: Allocator to use, or None (VkAllocationCallbacks*)
        surface: Where to store the handle of the surface (VkSurfaceKHR*)
        
    Returns:
        int: VkResult - VK_SUCCESS if successful
    """

Vulkan Physical Device Support

Check physical device presentation support for Vulkan queues.

def get_physical_device_presentation_support(instance, device, queuefamily: int) -> int:
    """
    Check whether the specified queue family supports presentation.
    
    This function returns whether the specified queue family of the 
    specified physical device supports presentation to the platform GLFW was built for.
    
    Parameters:
        instance: Vulkan instance handle (VkInstance)
        device: Physical device handle (VkPhysicalDevice)  
        queuefamily: Queue family index
        
    Returns:
        int: 1 if supported, 0 if not supported
    """

Vulkan Function Loading

Load Vulkan functions for the current instance.

def get_instance_proc_address(instance, procname: str) -> ctypes.c_void_p:
    """
    Get the address of the specified Vulkan instance function.
    
    This function returns the address of the specified Vulkan core or 
    extension function for the specified instance.
    
    Parameters:
        instance: Vulkan instance handle (VkInstance), or None for instance-independent functions
        procname: ASCII encoded name of the function
        
    Returns:
        ctypes.c_void_p: Function address, or None if function is not available
    """

Vulkan Loader Initialization

Configure the Vulkan loader before initialization (advanced usage).

def init_vulkan_loader(loader) -> None:
    """
    Set the desired Vulkan vkGetInstanceProcAddr function.
    
    This function sets the vkGetInstanceProcAddr function that GLFW will use for all 
    Vulkan related entry point queries.
    
    Parameters:
        loader: vkGetInstanceProcAddr function, or None to use default
    """

Window Hints for Vulkan

When creating windows for Vulkan rendering, set appropriate window hints:

# Vulkan-specific window hints
CLIENT_API: int = 0x00022001
NO_API: int = 0  # Disable OpenGL context creation for Vulkan

# Use with window_hint:
# glfw.window_hint(glfw.CLIENT_API, glfw.NO_API)

Usage Examples

Basic Vulkan Setup

import glfw
import ctypes

# Initialize GLFW
glfw.init()

# Check Vulkan support
if not glfw.vulkan_supported():
    glfw.terminate()
    raise Exception("Vulkan not supported")

# Get required extensions
extensions = glfw.get_required_instance_extensions()
print(f"Required Vulkan extensions: {extensions}")

# Create window without OpenGL context
glfw.window_hint(glfw.CLIENT_API, glfw.NO_API)
glfw.window_hint(glfw.RESIZABLE, glfw.FALSE)

window = glfw.create_window(800, 600, "Vulkan Window", None, None)
if not window:
    glfw.terminate()
    raise Exception("Failed to create window")

# ... Vulkan instance creation with required extensions ...
# instance = create_vulkan_instance_with_extensions(extensions)

# Create Vulkan surface
# surface = ctypes.c_void_p()
# result = glfw.create_window_surface(instance, window, None, ctypes.byref(surface))
# if result != VK_SUCCESS:
#     raise Exception("Failed to create Vulkan surface")

glfw.terminate()

Vulkan Function Loading

import glfw
import ctypes

glfw.init()

if not glfw.vulkan_supported():
    raise Exception("Vulkan not supported")

# Load Vulkan functions
vk_create_instance = glfw.get_instance_proc_address(None, "vkCreateInstance")
vk_enumerate_instance_extensions = glfw.get_instance_proc_address(None, "vkEnumerateInstanceExtensionProperties")

if vk_create_instance:
    print("Successfully loaded vkCreateInstance")

# After creating instance, load instance-specific functions
# instance = ...  # Created Vulkan instance
# vk_create_device = glfw.get_instance_proc_address(instance, "vkCreateDevice")
# vk_get_physical_devices = glfw.get_instance_proc_address(instance, "vkEnumeratePhysicalDevices")

glfw.terminate()

Complete Vulkan Window Creation

import glfw
import ctypes

def create_vulkan_window():
    glfw.init()
    
    # Verify Vulkan support
    if not glfw.vulkan_supported():
        glfw.terminate()
        raise Exception("Vulkan is not supported")
    
    # Get required instance extensions
    glfw_extensions = glfw.get_required_instance_extensions()
    print(f"GLFW requires these Vulkan extensions: {glfw_extensions}")
    
    # Create window for Vulkan (no OpenGL context)
    glfw.window_hint(glfw.CLIENT_API, glfw.NO_API)
    glfw.window_hint(glfw.RESIZABLE, glfw.TRUE)
    
    window = glfw.create_window(1024, 768, "Vulkan Application", None, None)
    if not window:
        glfw.terminate()
        raise Exception("Failed to create GLFW window")
    
    return window, glfw_extensions

def check_device_presentation_support(instance, physical_device, queue_family_index):
    """Check if a queue family supports presentation to GLFW windows."""
    return glfw.get_physical_device_presentation_support(
        instance, physical_device, queue_family_index
    ) == 1

# Usage
try:
    window, required_extensions = create_vulkan_window()
    
    # ... Create Vulkan instance with required_extensions ...
    # ... Enumerate physical devices ...
    # ... Check presentation support with check_device_presentation_support ...
    # ... Create logical device with presentation-capable queue ...
    # ... Create surface with glfw.create_window_surface ...
    
    # Main loop
    while not glfw.window_should_close(window):
        glfw.poll_events()
        
        # Vulkan rendering commands
        # ... vkQueueSubmit, vkQueuePresentKHR, etc. ...
    
finally:
    glfw.terminate()

Vulkan Surface Management

import glfw
import ctypes

class VulkanSurface:
    def __init__(self, instance, window):
        self.instance = instance
        self.window = window
        self.surface = ctypes.c_void_p()
        
        # Create the surface
        result = glfw.create_window_surface(
            instance, window, None, ctypes.byref(self.surface)
        )
        
        if result != 0:  # VK_SUCCESS = 0
            raise Exception(f"Failed to create Vulkan surface: {result}")
    
    def get_handle(self):
        return self.surface.value
    
    def cleanup(self):
        # In a real application, you would call vkDestroySurfaceKHR here
        # vkDestroySurfaceKHR(self.instance, self.surface, None)
        pass

# Usage example
glfw.init()

if glfw.vulkan_supported():
    glfw.window_hint(glfw.CLIENT_API, glfw.NO_API)
    window = glfw.create_window(800, 600, "Vulkan Surface", None, None)
    
    # ... create Vulkan instance ...
    # instance = create_instance()
    
    # surface = VulkanSurface(instance, window)
    # print(f"Created surface: 0x{surface.get_handle():x}")
    
    # ... use surface for swapchain creation ...
    
    # surface.cleanup()

glfw.terminate()

Vulkan Validation Layers

import glfw

def get_vulkan_extensions_with_validation():
    """Get Vulkan extensions including validation layer requirements."""
    
    # Get GLFW required extensions
    glfw_extensions = glfw.get_required_instance_extensions()
    
    # Add debug/validation extensions
    validation_extensions = ["VK_EXT_debug_utils"]
    
    # Combine extensions
    all_extensions = glfw_extensions + validation_extensions
    
    return all_extensions

def setup_vulkan_debug_callback():
    """Set up Vulkan debug callback for validation layers."""
    
    # Load debug function
    vk_create_debug_utils_messenger = glfw.get_instance_proc_address(
        None, "vkCreateDebugUtilsMessengerEXT"
    )
    
    if vk_create_debug_utils_messenger:
        print("Debug utils extension available")
        # ... set up debug callback ...
    else:
        print("Debug utils extension not available")

# Usage
glfw.init()

if glfw.vulkan_supported():
    extensions = get_vulkan_extensions_with_validation()
    print(f"Extensions for Vulkan with validation: {extensions}")
    
    # ... create instance with validation layers and extensions ...
    # setup_vulkan_debug_callback()

glfw.terminate()

Vulkan Multi-Window Support

import glfw
import ctypes

def create_vulkan_windows(count=2):
    """Create multiple windows for Vulkan rendering."""
    
    glfw.init()
    
    if not glfw.vulkan_supported():
        raise Exception("Vulkan not supported")
    
    glfw.window_hint(glfw.CLIENT_API, glfw.NO_API)
    
    windows = []
    for i in range(count):
        window = glfw.create_window(
            800, 600, f"Vulkan Window {i+1}", None, None
        )
        if not window:
            # Clean up previously created windows
            for w in windows:
                glfw.destroy_window(w)
            glfw.terminate()
            raise Exception(f"Failed to create window {i+1}")
        
        windows.append(window)
    
    return windows

def create_surfaces_for_windows(instance, windows):
    """Create Vulkan surfaces for multiple windows."""
    
    surfaces = []
    for i, window in enumerate(windows):
        surface = ctypes.c_void_p()
        result = glfw.create_window_surface(
            instance, window, None, ctypes.byref(surface)
        )
        
        if result != 0:
            print(f"Failed to create surface for window {i+1}")
            continue
            
        surfaces.append(surface.value)
    
    return surfaces

# Usage
try:
    windows = create_vulkan_windows(2)
    
    # ... create Vulkan instance ...
    # surfaces = create_surfaces_for_windows(instance, windows)
    
    # Main loop handling multiple windows
    while any(not glfw.window_should_close(w) for w in windows):
        glfw.poll_events()
        
        for i, window in enumerate(windows):
            if not glfw.window_should_close(window):
                # Render to window i
                # ... Vulkan rendering for this window/surface ...
                pass
    
finally:
    glfw.terminate()

Install with Tessl CLI

npx tessl i tessl/pypi-glfw

docs

index.md

input-handling.md

library-management.md

monitor-display.md

opengl-context.md

vulkan-support.md

window-management.md

tile.json