Vulkanite 是一个从零实现的 Vulkan 1.3 兼容 GPU 用户态驱动框架,涵盖 SPIR-V 着色器编译管线、命令缓冲区调度、描述符集管理与显存分配器。项目深入 GPU 驱动底层,展示了对现代图形 API 和 GPU 架构的深刻理解。
一、驱动架构概览
Vulkanite 采用分层架构:应用层(Vulkan API 入口)→ 命令流层(命令缓冲编码)→ 编译器层(SPIR-V → 原生 ISA)→ 内存管理层(显存分配与虚拟化)→ 内核接口层(ioctl 与内核驱动通信)。
typedef struct VulkaniteDriver {
VkPhysicalDeviceProperties properties;
VkPhysicalDeviceMemoryProperties memory_props;
VkPhysicalDeviceFeatures features;
// 命令缓冲区环形队列
CommandRingBuffer* cmd_ring;
// 着色器编译器
SpirvCompiler* compiler;
// 显存分配器
GpuMemoryAllocator* vram_alloc;
// 描述符堆
DescriptorHeap* desc_heap;
// 内核驱动文件描述符
int drm_fd;
} VulkaniteDriver;
二、SPIR-V 着色器编译管线
实现完整的 SPIR-V 二进制解析器,将 SPIR-V 模块转换为 GPU 原生 ISA。支持顶点着色器、片段着色器和计算着色器的编译,包含死代码消除、常量折叠和循环展开等优化 Pass。
typedef struct SpirvCompiler {
SpirvModule* module;
IsaEmitter* emitter;
RegisterAllocator* reg_alloc;
} SpirvCompiler;
// SPIR-V OpCode 到原生 ISA 的转换
static void translate_spirv_instruction(
SpirvCompiler* compiler, SpvOp opcode,
const uint32_t* operands, uint32_t operand_count)
{
switch (opcode) {
case SpvOpFMul:
emit_fmul(compiler->emitter,
operands[0], operands[1], operands[2]);
break;
case SpvOpFAdd:
emit_fadd(compiler->emitter,
operands[0], operands[1], operands[2]);
break;
case SpvOpVectorShuffle:
emit_vector_shuffle(compiler->emitter,
operands, operand_count);
break;
case SpvOpImageSampleImplicitLod:
emit_texture_sample(compiler->emitter,
operands, operand_count);
break;
}
}
三、命令缓冲区调度器
实现 Vulkan 命令缓冲区的录制与提交。命令缓冲区被编码为 GPU 可执行的命令流,通过环形缓冲区提交到 GPU 命令处理器。支持主命令缓冲区和辅助命令缓冲区的复用。
typedef struct CommandRingBuffer {
uint32_t* base; // 映射的 GPU 可见内存
uint32_t size; // 环形缓冲区大小(字节)
uint32_t write_ptr; // CPU 写入位置
volatile uint32_t* read_ptr; // GPU 读取位置(GPU 可写)
} CommandRingBuffer;
VkResult vkBeginCommandBuffer(VkCommandBuffer cmd_buf,
const VkCommandBufferBeginInfo* begin_info)
{
CommandBuffer* cb = (CommandBuffer*)cmd_buf;
cb->state = COMMAND_BUFFER_RECORDING;
cb->cmd_stream = create_command_stream(64 * 1024);
if (begin_info->flags & VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) {
cb->flags |= CB_ONE_TIME_SUBMIT;
}
return VK_SUCCESS;
}
VkResult vkQueueSubmit(VkQueue queue, uint32_t count,
const VkSubmitInfo* submits, VkFence fence)
{
for (uint32_t i = 0; i < count; i++) {
CommandBuffer* cb = (CommandBuffer*)submits[i].pCommandBuffers[0];
encode_indirect_buffer_packet(queue->cmd_ring, cb->cmd_stream);
}
ring_doorbell(queue->doorbell_offset);
return VK_SUCCESS;
}
四、显存分配器
实现基于 Buddy Allocator 的显存管理,支持不同内存类型(VRAM、GART、系统内存)的分配策略。使用稀疏纹理技术支持超大纹理的虚拟化管理。
typedef struct GpuMemoryAllocator {
BuddyAllocator vram_buddy; // 专用显存
BuddyAllocator gart_buddy; // GART 可交换内存
uint64_t total_vram;
uint64_t available_vram;
} GpuMemoryAllocator;
VkResult vkAllocateMemory(VkDevice device,
const VkMemoryAllocateInfo* alloc_info,
VkDeviceMemory* memory)
{
GpuMemoryAllocator* alloc = device->vram_alloc;
uint64_t size = alloc_info->allocationSize;
uint32_t type_index = alloc_info->memoryTypeIndex;
uint64_t offset;
if (type_index == MEMORY_TYPE_VRAM) {
offset = buddy_alloc(&alloc->vram_buddy, size, 4096);
} else {
offset = buddy_alloc(&alloc->gart_buddy, size, 4096);
}
*memory = create_device_memory(device, offset, size, type_index);
return VK_SUCCESS;
}
五、描述符集管理
实现 Vulkan 描述符集的分配与更新,支持 Uniform Buffer、Storage Buffer、Sampled Image 和 Storage Image 等描述符类型。使用描述符堆减少分配开销。
Vulkanite 展示了 GPU 驱动开发的核心技术栈,从 SPIR-V 编译到命令调度再到显存管理,是理解现代 GPU 工作原理的绝佳实践项目。
← 返回作品展示