Experimental Linux-native DirectStorage-style runtime (CPU today, GPU tomorrow) with an early GPU/Vulkan backend, towards Wine/Proton integration.
ds-runtime is an experimental C++ runtime that explores how a DirectStorage-style I/O and decompression pipeline can be implemented natively on Linux.
The project focuses on:
-
Clean, idiomatic systems-level C++
-
Explicit and auditable concurrency
-
POSIX-first file I/O
-
A backend-based architecture that cleanly separates:
-
request orchestration (queues, lifetime, synchronization)
-
execution backends (CPU now, Vulkan/GPU planned)
The long-term motivation is to provide a solid architectural foundation for a native Linux implementation of DirectStorage-like workloads, suitable for eventual integration with Wine / Proton.
This repository intentionally prioritizes structure, clarity, and correctness over premature optimization.
- Status: Experimental
- Backend: CPU (implemented)
- GPU/Vulkan backend: Experimental (file ↔ GPU buffer transfers)
The current codebase implements a complete, working CPU backend and a clean public API designed to support GPU-accelerated backends in the future.
This is:
-
A reference-quality runtime skeleton
-
A clean async I/O queue with pluggable backends
-
A realistic starting point for Linux-native asset streaming
-
A codebase meant to be read, reviewed, and extended
This is not:
-
A drop-in replacement for Microsoft DirectStorage
-
A performance benchmark
-
A full GPU decompression implementation (yet)
-
Production-ready middleware
Modern games increasingly rely on DirectStorage-style I/O to stream large assets (textures, meshes, shaders) efficiently from disk to memory and GPU. On Windows, DirectStorage provides a standardized API that reduces CPU overhead, minimizes copying, and enables better asset streaming at scale.
On Linux, no equivalent native API exists today.
As a result, Proton/Wine-based games that depend on DirectStorage semantics must either:
- Fall back to legacy, CPU-heavy I/O paths, or
- Emulate Windows behavior in user space with limited visibility into Linux-native async I/O, memory management, and GPU synchronization.
This creates a structural gap.
Without a native Linux-side abstraction:
- Asset streaming is fragmented across engines and ad-hoc thread pools
- CPU cores are wasted on I/O and decompression work that could be pipelined or offloaded
- GPU upload paths are often bolted on after the fact rather than designed into the I/O model
- Proton/Wine must translate Windows semantics without a clear Linux analogue
DirectStorage is not just “faster file I/O” — it is an architectural contract between the game, the OS, and the GPU.
A Linux-native DirectStorage-style runtime enables:
- A clear, explicit async I/O model built on Linux primitives (e.g. thread pools today, io_uring tomorrow)
- Batching and queue-based submission that matches how modern engines structure asset streaming
- A first-class path from disk → CPU → GPU, rather than implicit or engine-specific glue
- Cleaner integration points for Wine/Proton, avoiding opaque shims or duplicated logic
- An evolution path toward GPU-assisted decompression and copies via Vulkan
This is not about copying Windows APIs verbatim. It is about providing a native Linux abstraction that maps cleanly onto modern storage, memory, and GPU systems.
ds-runtime explores what such a runtime could look like on Linux:
- A small, explicit request/queue model inspired by DirectStorage semantics
- Pluggable backends (CPU today, Vulkan/GPU tomorrow)
- A stable C ABI suitable for integration into Wine/Proton or engines
- Clear ownership, lifetime, and synchronization rules
- Documentation that treats integration as a first-class concern
Even partial adoption of these ideas can reduce duplication, clarify I/O paths, and make asset streaming behavior more predictable on Linux.
The long-term goal is not to replace engines or drivers, but to provide a shared, understandable foundation for high-performance game I/O on Linux.
┌─────────────┐
│ Client │
│ (game/app) │
└──────┬──────┘
│ enqueue Request
▼
┌─────────────┐
│ ds::Queue │ ← orchestration, lifetime, waiting
└──────┬──────┘
│ submit
▼
┌────────────────────┐
│ ds::Backend │ ← execution (CPU / Vulkan / future)
└────────────────────┘
See docs/design.md for details on backend evolution.
ds::Request
Describes what to load:
-
POSIX file descriptor
-
Byte offset
-
Size
-
Destination pointer
-
Optional GPU buffer/offset for Vulkan-backed transfers
-
Operation (read/write)
-
Memory location (host or GPU buffer)
-
Compression mode
-
Optional GPU buffer handle + offset when using the Vulkan backend
-
Completion status / error
This maps cleanly to:
-
Linux I/O semantics
-
DirectStorage request descriptors
-
Future GPU-resident workflows
ds::Queue
Responsible for:
-
Collecting requests
-
Submitting them to a backend
-
Tracking in-flight work
-
Optional blocking via
wait_all() -
Retrieving completed requests via
take_completed()
The queue does not perform I/O itself.
ds::Backend
Abstract execution interface.
Error reporting:
ds::set_error_callbackinstalls a process-wide hook for rich diagnosticsds::report_erroremits subsystem/operation/file/line context and timestampsds::report_request_erroradds request-specific fields (fd/offset/size/memory)
Current implementation:
-
CPU backend
-
pread()/pwrite()-based I/O -
Vulkan backend (experimental)
-
pread()/pwrite()plus Vulkan staging buffer copies to GPU buffers -
io_uring backend (experimental)
-
io_uringhost I/O path (host memory only) -
Small internal thread pool
-
Demo “decompression” stage (uppercase transform); GDeflate is stubbed
Planned backends:
-
Vulkan compute backend (GPU copy / decompression)
-
Vendor-specific GPU paths
This mirrors how real DirectStorage systems are structured:
-
A front-end queue API
-
A backend that owns execution and synchronization
-
Clear separation between:
-
disk I/O
-
decompression
-
GPU involvement
Keeping these layers explicit makes the code:
-
Easier to reason about
-
Easier to test
-
Easier to extend without rewrites
-
Code hygiene goals
The project follows conventions expected by experienced Linux developers:
-
Header / implementation split
-
No global state
-
RAII throughout
-
Direct use of POSIX APIs (open, pread, close)
-
No exceptions crossing public API boundaries
-
Minimal but explicit threading
-
No macro or template magic
-
If something happens, it should be obvious where and why.
Modern Windows titles increasingly rely on DirectStorage-style APIs for asset streaming and decompression. On Linux, these calls are currently handled via compatibility-layer shims or fall back to traditional I/O paths.
This project explores what a native Linux runtime for DirectStorage-like workloads could look like, with an emphasis on:
- Correct API semantics
- Clean separation between queue orchestration and execution
- Explicit backend design (CPU today, GPU later)
- Compatibility with Wine / Proton architecture
The current implementation focuses on a CPU backend that provides:
- Asynchronous I/O semantics
- Explicit completion tracking
- A decompression stage hook (currently a demo transform)
This is intended as a foundational layer that could back a future
dstorage.dll implementation in Wine/Proton, with GPU acceleration added
incrementally once semantics and integration points are validated.
For integration guidance (including a no-shim option), see docs/wine_proton.md. For Arch Linux–specific Vulkan notes, see docs/archlinux_vulkan_integration.md.
The included demo program:
-
Writes a small test asset to disk
-
Enqueues two asynchronous requests:
-
One raw read
-
One “compressed” read (fake uppercase transform)
-
Submits them concurrently
-
Waits for completion
-
Prints the results
Example output:
[demo] starting DirectStorage-style CPU demo
[demo] wrote 41 bytes to demo_asset.bin
[demo] submitting 2 requests
[demo] waiting for completion (in-flight=2)
[demo] all requests completed (in-flight=0)
raw : "Hello DirectStorage-style queue on Linux!"
upper : "HELLO DIRECTSTORAGE-STYLE QUEUE ON LINUX!"
Additional demo:
ds_asset_streamingwrites a packed asset file and issues concurrent reads, exercising request offsets and the error reporting callback.
Linux
C++20 compiler (Clang or GCC)
pthreads
CMake ≥ 3.16
Vulkan SDK (optional, required for the Vulkan backend)
liburing (optional, required for the io_uring backend)
git clone https://github.com/infinityabundance/ds-runtime.git
cd ds-runtime
mkdir build
cd build
cmake ..
cmake --build .Run the demo:
# from inside build/examples/
./ds_demoEnable tests with:
cmake -B build -S . -DDS_BUILD_TESTS=ON
cmake --build build
ctest --test-dir buildRun the asset streaming demo:
# from inside build/examples/
./ds_asset_streamingThe build produces a shared object libds_runtime.so that exposes both the
C++ API (include/ds_runtime.hpp) and a C-compatible ABI (include/ds_runtime_c.h).
This makes it easier to integrate the runtime with non-C++ code or FFI layers
like Wine or Proton shims.
To link against the shared object from another project:
cc -I/path/to/ds-runtime/include \
-L/path/to/ds-runtime/build \
-lds_runtime \
your_app.cWhen built with Vulkan, you can construct a Vulkan backend and submit requests
with RequestMemory::Gpu to move data between files and GPU buffers. Requests
use gpu_buffer + gpu_offset to identify the destination/source GPU buffer.
├── CMakeLists.txt # Top-level CMake build configuration
│
├── include/ # Public C++ API headers
│ └── ds_runtime.hpp # Core DirectStorage-style runtime interface
│ └── ds_runtime_vulkan.hpp # Vulkan backend interface (experimental)
│ └── ds_runtime_uring.hpp # io_uring backend interface (experimental)
│
├── src/ # Runtime implementation
│ └── ds_runtime.cpp # Queue, backend, and CPU execution logic
│ └── ds_runtime_vulkan.cpp # Vulkan backend implementation
│ └── ds_runtime_uring.cpp # io_uring backend implementation
│
├── examples/ # Standalone example programs
│ ├── ds_demo_main.cpp # CPU-only demo exercising ds::Queue and requests
│ ├── asset_streaming_main.cpp # Asset streaming demo with concurrent reads
│ │
│ └── vk-copy-test/ # Experimental Vulkan groundwork
│ ├── copy.comp # Vulkan compute shader (GLSL)
│ ├── copy.comp.spv # Precompiled SPIR-V shader
│ ├── demo_asset.bin # Small test asset for GPU copy
│ ├── vk_copy_test.cpp # Vulkan copy demo (CPU → GPU → CPU)
├── docs/ # Design and architecture documentation
│ └── design.md # Backend evolution and architectural notes
│
├── assets/ # Non-code assets used by documentation
│ └── logo.png # Project logo displayed in README
│
├── README.md # Project overview, build instructions, roadmap
└── LICENSE # Apache-2.0 license
This project is not affiliated with Microsoft, Valve, or the Wine project.
However, it is intentionally structured so that:
-
ds::Requestcan map toDSTORAGE_REQUEST_DESC -
ds::Queuecan map to a DirectStorage queue object -
A Vulkan backend can integrate with Proton’s D3D12 → Vulkan interop
The goal is to explore what a native Linux DirectStorage-style runtime could look like, with real code and real execution paths.
✅ Vulkan backend (file ↔ GPU buffer transfers; compute copy/decompression planned)
◻️ Real compression format (CPU GDeflate first)
✅ io_uring backend (host memory)
◻️ Wine / Proton integration experiments
◻️ Real-world game testing
This project intentionally starts small and correct.
Discussion, feedback, and code review are welcome.
If you are a:
-
Linux systems developer
-
Graphics / Vulkan developer
-
Wine or Proton contributor
…your perspective is especially appreciated.
This project is licensed under the Apache License 2.0. See the LICENSE file for details.
Linux deserves first-class asset streaming paths — not just compatibility shims.
Even if this repository never becomes the solution, it aims to push that discussion forward with real, auditable code rather than speculation.