I’m running into this.. problem.. where I can’t proceed with my development without a real risk of frying hardware. But that’s not how the professionals do it. The professionals… emulate hardware.
true hardware emulation reproduces a device/register/ISA model; GPU virtualization presents a virtual device backed by a real GPU; and GPU simulation models the architecture for research. VirGL, for example, is explicitly a virtual 3D GPU for QEMU, while MGPUSim is an architectural simulator for AMD GCN3.
The NVIDIA / Radeon Emulator Emporium
Tier 0 — Foundation / generic GPU machines
These should form the base of the collection.
| Emulator / project | Target | What it gives you |
|---|---|---|
| QEMU VGA | Generic VGA | Baseline display-device emulation |
| QEMU std-vga | Bochs-compatible VGA | Modern-ish legacy VGA environment |
| QEMU Cirrus VGA | Cirrus GD5446 | Classic PC graphics |
| QEMU QXL | QXL | Virtualized 2D graphics |
| QEMU VMware SVGA | VMware SVGA | SVGA-era virtual GPU |
| QEMU virtio-gpu | VirtIO | Modern paravirtual GPU |
| VirGL | OpenGL/Gallium | Virtual 3D GPU |
| Venus | Vulkan | Vulkan-over-VirtIO |
| rutabaga_gfx | Vulkan/GLES | VirtIO graphics backend |
| gfxstream | Vulkan/GLES | Guest graphics translation |
| SwiftShader | CPU | Software GPU/Vulkan/OpenGL implementation |
| LLVMpipe | CPU | Software Gallium GPU |
| Softpipe | CPU | Reference Gallium software renderer |
| Zink | Vulkan | OpenGL implemented over Vulkan |
QEMU currently exposes virtio-gpu variants including virtio-vga, virtio-gpu, vhost-user-vga, and vhost-user-pci, with VirGL and rutabaga as accelerated backends.
ATI / AMD / Radeon wing
This is where the emporium gets really interesting, because the Radeon family divides naturally into hardware generations.
ATI R100
Target architecture: Radeon 7000 / R100
Collect:
- Radeon R100
- Radeon 7200
- Radeon 7000
- RV100
- Radeon VE
- Mobility Radeon 7000
Emulator target
R100 register/MMIO emulator
Architecture to reproduce:
PCI
│
├── BAR0 MMIO
├── framebuffer
├── CRTC
├── DAC
├── 2D engine
├── command processor
└── R100 acceleration
This becomes your first genuinely interesting bare-metal Radeon machine.
ATI R200
Target: Radeon 8500/8500LE
Models:
- R200
- RV200
- Radeon 8500
- Radeon 8500LE
- Radeon 9100
- Radeon 9000
- Radeon 9200
The R200 generation is historically valuable because it gives you an early programmable-ish 3D architecture while remaining relatively tractable.
A Mesa retro survey confirms R200-era hardware such as the Radeon 8500 was supported by historical Mesa stacks.
ATI R300
Target: Radeon 9500–9800 generation
Models:
- R300
- R350
- R360
- RV350
- RV360
- Radeon 9500
- Radeon 9600
- Radeon 9700
- Radeon 9800
- Radeon X300
- Radeon X600
This is a prime emulator target.
Why?
R300 gives you a much more interesting programmable graphics pipeline while still being sufficiently old that the architecture is comprehensible.
Mesa’s historical support includes R300/RV515-era hardware.
ATI R400
Models:
- R420
- R423
- R430
- R480
- Radeon X700
- Radeon X800
- Radeon X850
This is an excellent second-generation Radeon emulator.
The Linux Radeon driver family historically contains distinct R420-family firmware, which is another useful source when reconstructing the hardware model.
ATI R500
Models:
- R520
- R515
- R530
- R580
- Radeon X1300
- X1600
- X1800
- X1900
- X1950
This is where I’d build a dedicated:
R500 Command Processor Emulator
with:
PCI
MMIO
VRAM
DMA
CP
2D
3D
vertex processing
fragment processing
display controller
interrupts
R520-family hardware also has identifiable firmware components in the Linux driver ecosystem.
R600
This one deserves its own room.
Models:
- R600
- RV610
- RV620
- RV630
- RV635
- RV670
- Radeon HD 2400
- HD 2600
- HD 2900
R600 is the beginning of the unified-shader era.
A very attractive emulator target:
R600 GPU
├── Command Processor
├── Shader ALUs
├── Texture units
├── Render backend
├── VRAM
├── DMA
├── UVD
└── display engine
The Linux Radeon stack has separate R600 ME, PFP, RLC and UVD firmware components, giving you useful architectural boundaries to reproduce.
R700
Models:
- R700
- RV710
- RV730
- RV740
- RV770
- RV790
- Radeon HD 4000
This is probably one of the best complete Radeon emulator targets.
Why?
You can create a coherent machine rather than merely emulating a display adapter.
Evergreen
Radeon HD 5000
Architectures:
- Cypress
- Juniper
- Redwood
- Cedar
- Hemlock
Examples:
- HD 5450
- HD 5570
- HD 5770
- HD 5850
- HD 5870
- HD 5970
The Linux driver contains separate Evergreen microcode components such as Redwood ME/PFP/RLC/SMC, which makes the generation especially interesting for reverse-engineering-oriented emulation.
Northern Islands
Radeon HD 6000
Targets:
- Barts
- Cayman
- Turks
- Caicos
- Antilles
Examples:
- HD 6450
- HD 6670
- HD 6850
- HD 6870
- HD 6950
- HD 6970
Southern Islands
This is another major emulator milestone.
Architectures:
- Tahiti
- Pitcairn
- Cape Verde
- Oland
- Bonaire
Examples:
- HD 7750
- HD 7770
- HD 7850
- HD 7870
- HD 7950
- HD 7970
- R9 270
- R9 280
This gives you GCN.
And this is particularly interesting because MGPUSim currently provides stable simulation for AMD GCN3, including multi-GPU simulation.
Sea Islands
- Hawaii
- Bonaire
- Kaveri-related GCN
- R9 290
- R9 290X
- R9 285
Volcanic Islands
- Fiji
- Tonga
- Carrizo
- R9 Fury
- R9 Nano
Polaris
Targets:
- Polaris 10
- Polaris 11
- Polaris 12
- Polaris 20
- Polaris 21
- Polaris 22
- RX 460
- RX 470
- RX 480
- RX 550
- RX 560
- RX 570
- RX 580
- RX 590
Polaris is particularly attractive because the device IDs and GPU families are well documented and still have substantial driver support.
Vega
Targets:
- Vega 10
- Vega 11
- Vega 12
- Vega 20
- Radeon VII
- RX Vega 56
- RX Vega 64
This becomes the high-end GCN laboratory.
RDNA
Then split the modern Radeon wing:
RDNA 1
- Navi 10
- Navi 12
- Navi 14
- RX 5000
RDNA 2
- Navi 21
- Navi 22
- Navi 23
- Navi 24
- RX 6000
RDNA 3
- Navi 31
- Navi 32
- Navi 33
- RX 7000
RDNA 4
- RX 9000 generation
- current RDNA4 architectures
These shouldn’t initially be cycle-accurate emulators. I’d treat them as progressively richer device models:
PCI identity
↓
BAR/MMIO
↓
VRAM
↓
command processor
↓
queue model
↓
ISA interpreter
↓
shader execution
↓
display
↓
compute
NVIDIA wing
Now the fun side.
NVIDIA NV1
The historical oddball.
NVIDIA NV1
- quadratic texture mapping
- early proprietary 3D architecture
- Sega Saturn-derived concepts
Absolutely worth having in an emporium simply because it is so weird.
RIVA
NV3
RIVA 128
NV4
RIVA TNT
NV5
RIVA TNT2
These make excellent early NVIDIA emulator targets.
GeForce 256
NV10
This is a major milestone:
hardware transform & lighting.
Your emulator now becomes:
CPU
│
└── command stream
│
▼
NV10 GPU
│
├── geometry
├── T&L
├── raster
├── texture
└── framebuffer
GeForce 2
NV15 / NV11
Targets:
- GeForce 2 GTS
- GeForce 2 MX
- GeForce 2 Ultra
GeForce 3
NV20
Very important.
Programmable vertex/pixel shaders.
GeForce 4
NV25 / NV28
Targets:
- GeForce4 Ti
- GeForce4 MX
Mesa’s historical driver list specifically includes NVIDIA Riva TNT through GeForce 4 hardware.
GeForce FX
NV30 / NV35 / NV40
Models:
- GeForce FX 5200
- FX 5600
- FX 5700
- FX 5800
- FX 5900
- FX 5950
This would make a fantastic shader emulator.
GeForce 6
NV40 / NV43
- GeForce 6800
- 6600
- 6200
GeForce 7
G70 / G71 / G72 / G73
- 7800
- 7900
- 7600
- 7300
Tesla
This deserves its own wing.
G80
- GeForce 8800
- Tesla architecture
G92
- 8800 GT
- 9800 GT
- etc.
GT200
- GTX 260
- GTX 275
- GTX 280
- GTX 285
Now you’re dealing with CUDA-capable NVIDIA hardware architecture.
Nouveau provides open-source Linux kernel/GL/Vulkan support for a large span of NVIDIA hardware, making it one of the important software references for an NVIDIA emulation laboratory.
Fermi
Targets:
- GF100
- GF104
- GF106
- GF108
- GF110
- GF114
- GF116
- GF118
Examples:
- GTX 460
- GTX 470
- GTX 480
- GTX 570
- GTX 580
Kepler
Targets:
- GK104
- GK106
- GK107
- GK110
- GK208
Examples:
- GTX 680
- GTX 760
- GTX 770
- GTX 780
- GTX Titan
This is an excellent CUDA-era emulator target.
Maxwell
GM10x
- GTX 750
- GTX 750 Ti
GM20x
- GTX 950
- GTX 960
- GTX 970
- GTX 980
- GTX Titan X
Pascal
- GP100
- GP102
- GP104
- GP106
- GP107
- GP108
Examples:
- GTX 1050
- GTX 1060
- GTX 1070
- GTX 1080
- Titan X
- Tesla P100
Volta
- GV100
- Titan V
- Tesla V100
Turing
- TU102
- TU104
- TU106
- TU116
- TU117
Examples:
- RTX 2060
- RTX 2070
- RTX 2080
- RTX 2080 Ti
- GTX 1650–1660 family
Ampere
- GA100
- GA102
- GA104
- GA106
- GA107
Examples:
- RTX 3060
- RTX 3070
- RTX 3080
- RTX 3090
- A100
Ada Lovelace
- AD102
- AD103
- AD104
- AD106
- AD107
Examples:
- RTX 4060
- RTX 4070
- RTX 4080
- RTX 4090
Blackwell
Then:
- GB100
- GB200 family
- RTX 50-series architectures
- Blackwell data-center GPUs
I’d treat these as architectural simulators first, rather than attempting literal device emulation.
The really interesting emulators
And I’d put a separate Experimental Laboratory in the middle of the emporium.
1. MGPUSim
AMD GCN simulation.
It already supports multi-GPU simulation and is designed specifically as a high-performance/high-accuracy GPU simulator.
2. VirGL
Virtual GPU with host-side rendering.
3. Venus
Vulkan → VirtIO → host GPU.
4. rutabaga_gfx
gfxstream/Vulkan/Wayland-oriented virtualization.
5. Nouveau
Not an emulator, but an extremely valuable NVIDIA architectural reference because it exposes generations of NVIDIA hardware through an open-source driver stack.
6. Mesa R300/R600/RadeonSI
Likewise, not emulators, but invaluable if you’re constructing Radeon hardware models. Mesa maintains the historical architecture/driver lineage, including R300 and R600-era families.
7. QEMU
Your machine chassis.
Instead of building every emulator as an independent VM, make QEMU the PCI/BIOS/CPU/RAM/I/O substrate and plug GPU models into it.
Mesa VirGL Documentation
QEMU VirtIO GPU Documentation
MGPUSim — AMD GCN GPU Simulator
Nouveau — Open-Source NVIDIA Driver
Mesa Systems / Historical GPU Driver Support
Historical Mesa R200 / Radeon Information
https://gist.github.com/arkadijs/c847760105f56ee79034bda46a87e325
Radeon Firmware / Driver Reference
https://gist.github.com/persianyagami90xs/fc3540fc6b75cae00403ee922b32ee1b
Dortania AMD GPU Buyers Guide
https://github.com/dortania/GPU-Buyers-Guide/blob/master/modern-gpus/amd-gpu.md
The important conceptual shift is that we’re not really building “GPU emulators.” We’re building a time machine for GPU architecture.
The common interface becomes the invariant, while each generation implements its own machine.
GPU EMPORIUM
│
┌─────────┴─────────┐
│ │
RADEON NVIDIA
│ │
┌─────────┼─────────┐ ┌─────┼─────────────┐
│ │ │ │ │ │
R100 R300 R600 NV10 NV20 NV30
│ │ │
R700 NV40 │
│ │ │
GCN3 G80 │
│ │
TESLA ──────────┘
│ │
└─────────┬─────────┘
│
┌─────────▼─────────┐
│ UNIVERSAL GPU ABI │
├────────────────────┤
│ PCI configuration │
│ BARs │
│ MMIO │
│ VRAM │
│ DMA │
│ interrupts │
│ command submission │
│ registers │
│ shaders │
│ textures │
│ framebuffer │
└─────────┬──────────┘
│
┌───────────▼───────────┐
│ GUEST MACHINE │
│ │
│ BIOS → OS → DRIVER │
│ → GPU │
└───────────────────────┘
The really powerful part
Don’t make the universal layer pretend every GPU works the same.
Instead, define a minimum hardware contract:
GPUDevice
├── pci_config()
├── bar_read()
├── bar_write()
├── vram_read()
├── vram_write()
├── mmio_read()
├── mmio_write()
├── dma()
├── interrupt()
├── reset()
└── tick()
Then each actual GPU gets its own personality.
R100Device
R300Device
R600Device
R700Device
GCN3Device
NV10Device
NV20Device
NV30Device
NV40Device
G80Device
TeslaDevice
The guest doesn’t get to know that it’s an emulator.
It sees:
PCI
└── AMD/ATI VGA controller
├── BAR0
├── BAR1
├── framebuffer
└── interrupt
or:
PCI
└── NVIDIA VGA controller
├── BAR0
├── BAR1
├── VRAM
└── interrupt
And that is where your HDGL work becomes particularly relevant.
You can eventually have:
x86 MACHINE
│
┌────────▼────────┐
│ BIOS │
└────────┬────────┘
│
PCI ENUMERATION
│
┌────────▼────────┐
│ GPU DEVICE │
└────────┬────────┘
│
┌──────────────┼──────────────┐
│ │ │
MMIO VRAM DMA
│ │ │
└──────────────┼──────────────┘
│
COMMAND PROCESSOR
│
┌──────▼──────┐
│ GPU ENGINE │
└──────┬──────┘
│
┌─────────┼─────────┐
│ │ │
shader texture raster
And then comes the killer feature
Every emulator gets an architectural trace recorder.
For example:
R300 TRACE
────────────────────────────────────
PCI WRITE
BAR0 + 0x4F00
= 0x00000001
MMIO WRITE
CP_RB_WPTR
= 0x00000420
DMA
VRAM[0x00100000]
← RAM[0x00800000]
length = 4096
COMMAND
DRAW_INDEX
VERTEX
x=...
y=...
z=...
PIXEL
shader #17
FRAMEBUFFER
1024 × 768 × 32
Then run the same workload through:
R300
R600
R700
GCN3
and observe how the machine accomplishes essentially the same computational task through completely different architectures.
That gives you something almost no ordinary emulator collection provides:
An executable evolutionary tree.
FIXED FUNCTION
│
├── R100
│
├── NV10
│
▼
PROGRAMMABLE VERTEX/PIXEL
│
├── R300
├── NV20
├── NV30
└── NV40
│
▼
UNIFIED SHADER
│
├── R600
├── R700
└── G80
│
▼
GENERAL GPU COMPUTE
│
├── GCN
└── Tesla
│
▼
MODERN GPU
And I would not start by implementing OpenGL.
I’d start with the lowest layer:
PCI → BAR → MMIO → VRAM → command processor → interrupt.
Then get one ancient card to successfully execute a tiny command stream.
Once that works, the rest becomes evolutionary:
emulator/
│
├── core/
│ ├── pci.py
│ ├── mmio.py
│ ├── vram.py
│ ├── dma.py
│ ├── irq.py
│ └── trace.py
│
├── ati/
│ ├── r100.py
│ ├── r300.py
│ ├── r600.py
│ ├── r700.py
│ └── gcn3.py
│
├── nvidia/
│ ├── nv10.py
│ ├── nv20.py
│ ├── nv30.py
│ ├── nv40.py
│ ├── g80.py
│ └── tesla.py
│
├── guest/
│ ├── bios.py
│ ├── pci_scan.py
│ └── diagnostics.py
│
└── machines/
├── qemu.py
└── baremetal.py
R100 and NV10 would be the two founding exhibits.
One ATI. One NVIDIA. Both old enough that we can actually understand the entire machine rather than drowning immediately in modern GPU complexity.
Then R300/NV20.
Then R600/NV40.
Then R700/G80.
Then GCN3/Tesla.