This project implements a bare-metal C Graphics Driver API designed to interface a CPU application with the GPU Compute Core over the Unified Memory interconnect. It handles low-level command formatting, circular ring-buffer management, and Memory-Mapped IO (MMIO) doorbell signaling to trigger hardware execution.
Because the SoC utilizes a Unified Memory Architecture (UMA), the driver does not need to perform expensive PCI Express copies from CPU system memory to GPU dedicated VRAM. Instead, it allocates buffers in a shared DRAM heap using uma_alloc(), allowing the GPU to read geometry data directly from the pointers written by the CPU.
To prevent the CPU from stalling while the GPU executes rendering tasks, the driver implements an asynchronous Command Ring Buffer:
- GPU Commands: Command packets are structured as a 128-byte packet containing an
opcode(e.g.,GPU_CMD_DRAW_TRI,GPU_CMD_DISPATCH_RT) and a set of payload parameters (such as memory pointers to vertex buffers). - Circular Queue: The CPU pushes commands to the head of the buffer (
write_ptr) and wraps around once the capacity is reached. - MMIO Doorbell: After writing commands to the buffer, the driver writes the updated tail index to a Memory-Mapped register (
doorbell_reg). Writing to this hardware address acts as an interrupt/signal that wakes up the GPU execution scheduler.
include/driver_core.h: Declares command structures, ring buffer control blocks, and MMIO register offsets.src/driver_core.c: Implements ring buffer initialization (gpu_ring_init), thread-safe command submission (gpu_ring_push), and doorbell signaling.test/test_driver.c: A user-space mock unit test that runs the entire software pipeline in isolation.
We verify the driver using a mock C testbench that simulates the hardware registers in software:
- Allocates a mock physical DRAM heap in memory.
- Initializes the GPU Ring Buffer.
- Submits a
DRAW_TRIcommand (draw triangle). - Submits a
DISPATCH_RTcommand (dispatch ray-tracing). - Asserts that the tail index and the MMIO Doorbell register are correctly incremented to
2.
Navigate to the project directory and compile using GCC:
gcc src/driver_core.c test/test_driver.c -I include -o test_driver
./test_driverExpected output:
Starting Graphics Driver API Test...
Ring buffer initialized at 0x... with capacity 64
Pushing Draw Triangle command to ring buffer...
Pushing Ray Tracing Dispatch command to ring buffer...
Tail Index is now: 2
Hardware Doorbell Register value: 2
Test Passed: Ring buffer mechanics and MMIO doorbell function correctly!