gpu

package module
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 9, 2026 License: BSD-3-Clause Imports: 2 Imported by: 1

README

go-virtio/gpu

Pure-Go virtio-gpu (2D framebuffer) driver targeting the go-virtio/common transport interfaces. Implements the modern-transport (Virtio 1.0+) init sequence and the control-queue command path for the standard PCI-bound virtio-gpu device (VID 0x1AF4, DID 0x1050).

Scope

2D framebuffer only. 3D / virgl is explicitly out of scope: it requires a Mesa-class GL/Vulkan stack to generate the OpenGL command streams the host consumes, which does not exist in Go. The driver negotiates exactly VIRTIO_F_VERSION_1 and deliberately does not negotiate VIRTIO_GPU_F_VIRGL (bit 0), keeping the device in plain 2D mode (Virtio 1.1 §5.7).

Like the sibling drivers this package owns device bring-up, both virtqueues — the control queue (controlq, carrying every 2D command) and the cursor queue (cursorq, set up for spec-completeness but unused) — and the on-the-wire virtio-gpu control protocol. Every command is a 2-descriptor chain (a read-only request followed by a device-writable response), built with common.AddChain.

It exposes a scanout-enumeration + framebuffer API:

  • DisplayInfo lists the device's scanouts (GET_DISPLAY_INFO).
  • SetupFramebuffer creates a host 2D resource, attaches guest backing, and binds it to a scanout (RESOURCE_CREATE_2D + RESOURCE_ATTACH_BACKING + SET_SCANOUT). The returned Framebuffer.Pix is a BGRA byte buffer the caller draws into.
  • Framebuffer.Flush pushes the drawn pixels to the host and refreshes the scanout (TRANSFER_TO_HOST_2D + RESOURCE_FLUSH).

Quick start

import (
    virtiogpu "github.com/go-virtio/gpu"
)

// transport is any value that implements go-virtio/common.Transport.
g, err := virtiogpu.OpenVirtioGPU(transport)
if err != nil {
    return err
}

displays, err := g.DisplayInfo()
if err != nil {
    return err
}
d := displays[0] // first scanout

fb, err := g.SetupFramebuffer(d.ScanoutID, d.Width, d.Height)
if err != nil {
    return err
}

// Draw BGRA pixels into fb.Pix, then push to the display.
for i := 0; i+3 < len(fb.Pix); i += 4 {
    fb.Pix[i+0] = 0x20 // B
    fb.Pix[i+1] = 0x80 // G
    fb.Pix[i+2] = 0xFF // R
    fb.Pix[i+3] = 0xFF // A
}
err = fb.Flush()

Sibling packages

License

BSD-3-Clause. See LICENSE.

Documentation

Overview

Package gpu is a pure-Go virtio-gpu (2D framebuffer) driver. It drives a modern (Virtio 1.0+) PCI virtio-gpu device through the transport interfaces defined in github.com/go-virtio/common; the same code drives a UEFI-backed device, a bare-metal device, or a virtio-mmio device depending on which common.Transport implementation the caller supplies.

Scope — 2D FRAMEBUFFER ONLY. The driver negotiates exactly VIRTIO_F_VERSION_1 and deliberately does NOT negotiate VIRTIO_GPU_F_VIRGL (bit 0), so the device operates in plain 2D mode (Virtio 1.1 §5.7). 3D / virgl acceleration is out of scope: it requires a Mesa-class GL/Vulkan stack to generate the OpenGL command streams the host consumes, and no such stack exists in Go.

The driver owns device bring-up, the control virtqueue (controlq), the cursor virtqueue (cursorq, set up but unused), and the on-the-wire virtio-gpu control protocol (every command is a 2-descriptor chain: a read-only request followed by a device-writable response). It exposes a scanout-enumeration + framebuffer API:

  • DisplayInfo lists the device's scanouts (GET_DISPLAY_INFO).
  • SetupFramebuffer creates a host resource, attaches guest backing, and binds it to a scanout (RESOURCE_CREATE_2D + RESOURCE_ATTACH_BACKING + SET_SCANOUT). The returned Framebuffer's Pix is a BGRA byte buffer the caller draws into.
  • Framebuffer.Flush pushes the drawn pixels to the host and refreshes the scanout (TRANSFER_TO_HOST_2D + RESOURCE_FLUSH).

References:

  • Virtio 1.1 §5.7 "GPU Device" — device-type 16 binding.
  • Virtio 1.1 §5.7.4 "Device configuration layout" — virtio_gpu_config.
  • Virtio 1.1 §5.7.6 "Device Operation" — control + cursor queues, struct virtio_gpu_ctrl_hdr and the 2D command structs.
  • Virtio 1.1 §3.1.1 "Device Initialization".

Index

Constants

View Source
const (
	ControlQueueIdx uint16 = 0
	CursorQueueIdx  uint16 = 1
)

Queue indices (Virtio 1.1 §5.7.2). The control queue carries every 2D command; the cursor queue carries cursor updates and is set up for spec-completeness but otherwise unused by this driver.

View Source
const (
	ControlQueueSize uint16 = 16
	CursorQueueSize  uint16 = 16
)

ControlQueueSize / CursorQueueSize are the desired ring sizes (clamped + rounded during setup). Commands are issued one at a time, so a small ring is plenty.

View Source
const AcceptedFeatures uint64 = common.FeatureVersion1

AcceptedFeatures is the feature mask the driver negotiates ON — only the non-negotiable VIRTIO_F_VERSION_1. VIRTIO_GPU_F_VIRGL (bit 0) is deliberately NOT accepted, keeping the device in 2D mode.

View Source
const CommandPollIterations = 200000

CommandPollIterations is the busy-poll budget spent waiting for the device to complete one control command.

View Source
const DeviceType uint16 = 16

DeviceType is the virtio device-type encoding for virtio-gpu (Virtio 1.1 §5.7.1). Retained for callers enumerating PCI devices that want a stable name.

Variables

View Source
var (
	ErrNotModernDevice     = commonGPUError("go-virtio/gpu: device doesn't offer VIRTIO_F_VERSION_1 (legacy-only)")
	ErrFeaturesNotOK       = commonGPUError("go-virtio/gpu: FEATURES_OK status bit didn't stick after DriverFeature write")
	ErrInitWrongDeviceID   = commonGPUError("go-virtio/gpu: PCI device ID is not 0x1050 (modern GPU device)")
	ErrQueueNotAvailable   = commonGPUError("go-virtio/gpu: device reports QueueSize=0 for a required queue")
	ErrRequestTimeout      = commonGPUError("go-virtio/gpu: command poll timeout (device did not complete the command)")
	ErrGPUCommandFailed    = commonGPUError("go-virtio/gpu: device returned an error response to a control command")
	ErrNoScanout           = commonGPUError("go-virtio/gpu: no usable scanout (none enabled, or scanout id out of range)")
	ErrFramebufferTooLarge = commonGPUError("go-virtio/gpu: framebuffer dimensions are zero or exceed the supported bound")
)

Sentinel errors for the virtio-gpu path.

Functions

func AcceptFeatures

func AcceptFeatures(deviceFeatures uint64) (uint64, error)

AcceptFeatures returns the negotiated mask (requires VERSION_1).

Types

type Display

type Display struct {
	ScanoutID     uint32
	Width, Height uint32
	Enabled       bool
}

Display describes one scanout reported by GET_DISPLAY_INFO.

type Framebuffer

type Framebuffer struct {
	// Pix is the BGRA pixel buffer, width*height*4 bytes. The caller
	// writes pixels here, then calls Flush to display them.
	Pix []byte

	Width, Height uint32
	ResourceID    uint32
	// contains filtered or unexported fields
}

Framebuffer is a host 2D resource bound to a scanout, backed by a guest BGRA pixel buffer the caller draws into and then pushes via Flush.

func (*Framebuffer) Flush

func (fb *Framebuffer) Flush() error

Flush pushes the drawn pixels to the host resource and refreshes the scanout: TRANSFER_TO_HOST_2D(rect{0,0,W,H}, offset=0) then RESOURCE_FLUSH(rect{0,0,W,H}).

type VirtioGPU

type VirtioGPU struct {
	// Cfg is the modern-transport handle.
	Cfg *common.ModernConfig

	// NumScanouts is the device's advertised scanout count, read from
	// virtio_gpu_config.num_scanouts at Open.
	NumScanouts uint32

	// NegotiatedFeatures records the driver-feature handshake result.
	NegotiatedFeatures uint64
	// contains filtered or unexported fields
}

VirtioGPU wraps one initialised virtio-gpu device in 2D mode.

func OpenVirtioGPU

func OpenVirtioGPU(t common.Transport) (*VirtioGPU, error)

OpenVirtioGPU drives the full bring-up of one virtio-gpu device:

  1. Verify the PCI device ID is 0x1050 (modern GPU).
  2. InitModernConfig walks PCI caps + populates the BAR locators.
  3. Reset → ACK → DRIVER status progression.
  4. Read DeviceFeature, require VERSION_1, mask to VERSION_1 (NOT VIRGL), write DriverFeature.
  5. Set FEATURES_OK, verify it stuck.
  6. Allocate + publish controlq (queue 0) and cursorq (queue 1).
  7. DRIVER_OK status.
  8. Read num_scanouts (le32) from DeviceCfg offset 8.

func (*VirtioGPU) ControlQueue

func (g *VirtioGPU) ControlQueue() *common.Virtqueue

ControlQueue exposes the control virtqueue handle for diagnostics.

func (*VirtioGPU) DisplayInfo

func (g *VirtioGPU) DisplayInfo() ([]Display, error)

DisplayInfo issues GET_DISPLAY_INFO and parses the fixed array of 16 virtio_gpu_display_one entries into one Display per scanout index.

func (*VirtioGPU) SetupFramebuffer

func (g *VirtioGPU) SetupFramebuffer(scanoutID, width, height uint32) (*Framebuffer, error)

SetupFramebuffer creates a 2D BGRA resource, attaches a guest-allocated backing store, and binds it to scanoutID:

  1. RESOURCE_CREATE_2D(resource_id=1, format=BGRA, width, height).
  2. Allocate ceil(width*height*4 / PageSize) contiguous pages; hold the []byte as Pix (sliced to width*height*4).
  3. RESOURCE_ATTACH_BACKING(resource_id=1, one mem_entry = {phys, size}).
  4. SET_SCANOUT(scanout_id, resource_id=1, rect{0,0,width,height}).

Directories

Path Synopsis
Package soft3d is a minimal, dependency-free software 3D rasterizer.
Package soft3d is a minimal, dependency-free software 3D rasterizer.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL