LuisaCompute compiles one C++ kernel into CUDA, Metal and DirectX backends
High-Performance Rendering Framework on Stream Architectures
At a glance
- What is it?
- LuisaCompute is an Apache-2.0 licensed C++ framework for graphics and compute that hides the fragmentation between graphics APIs behind an embedded domain-specific language, a unified runtime and multiple backends. The interesting part is that the DSL is not a new language at all, it is C++ meta-programming that traces kernels into an AST, and the cost of that design is that you write against what the abstraction can express.
- Who is it for?
- LuisaCompute fits a graphics or simulation engineer who has to ship the same kernels to NVIDIA, Apple and Windows hardware and does not want three sets of shader code. It does not fit a project that needs a platform API feature the abstraction does not model, and it does not fit a team that will not maintain a C++ and Python build.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Three components, aimed at a single goal
The README states the ambition first and the design second. LuisaCompute seeks to balance the seemingly ever-conflicting pursuits of unification, programmability and performance, and to achieve this it designs three major components.
The first is a domain-specific language embedded inside modern C++ for kernel programming, exploiting JIT code generation and compilation. The second is a unified runtime with resource wrappers for cross-platform resource management and command scheduling. The third is multiple optimized backends, including CUDA, DirectX, Metal and CPU.
The audience is graphics and simulation engineers who want to write a kernel once. That is a real and recurring problem. The conventional route is to write the kernel in a shading language for each API, keep three copies in step, and accept that the fastest one is the one you develop against. The framework's answer is to make the source one artefact and let the backends generate the platform-specific shader.
The project is the rendering framework described in the SIGGRAPH Asia 2022 paper, LuisaRender: A High-Performance Rendering Framework with Layered and Unified Interfaces on Stream Architectures, with the paper linked by its DOI. The rendering application itself, LuisaRender, lives in a separate repository and is the demonstration of the framework's practicality, described as a Monte Carlo renderer that is faster than the state of the art rendering frameworks on modern GPUs.
There is also a project site at luisa-render.com, documentation at luisa-render.com/LuisaCompute, and a Discord channel. The repository shows applications built on top of the framework, including SMARAY, a GPU-native offline 3D rendering engine, Genesis, a generative world for general-purpose robotics and embodied AI learning, and libuipc, a C++20 library of unified incremental potential contact, which is a good indication of the domain the framework is used in.
The DSL is C++ meta-programming, not a new language
The mechanism is the part of the design that a reader has to understand to predict what the framework can and cannot express.
The README is explicit that the implementation purely relies on the C++ language itself, without any custom preprocessing pass or compiler extension. Meta-programming techniques are used to simulate the syntax, and function and operator overloading to dynamically trace the user-defined kernels. ASTs are constructed during the tracing as an intermediate representation and later handed over to the backends for generating concrete, platform-dependent shader source code.
So the $if and $else in the example are not a preprocessor. They are C++ constructs, spelled in a way that meta-programming can intercept, and the tracing pass is what turns a kernel body into an AST. The backends then compile that AST into whatever CUDA, HLSL or Metal source the destination needs.
Here is the example from the README, which shows both halves of the model in a few lines.
Callable to_srgb = [](Float3 x) {
$if (x <= 0.00031308f) {
x = 12.92f * x;
} $else {
x = 1.055f * pow(x, 1.f / 2.4f) - .055f;
};
return x;
};
Kernel2D fill = [&](ImageFloat image) {
auto coord = dispatch_id().xy();
auto size = make_float2(dispatch_size().xy());
auto rg = make_float2(coord) / size;
// invoke the callable
auto srgb = to_srgb(make_float3(rg, 1.f));
image.write(coord, make_float4(srgb, 1.f));
};The host-side and the device-side are the same language, which the README calls out as the distinction from typical graphics APIs that use standalone shading languages for device code. A Callable is a device function that can be called from a kernel, and a Kernel2D is the entry point with the built-in dispatch_id and dispatch_size intrinsics giving the thread coordinates.
The benefit is real: no separate language, no separate compiler, and the type system carries across the host and device boundary. The cost is that the DSL is a constrained subset of C++ that the tracing pass understands, and anything the tracer cannot model is a problem you have to solve another way.
The runtime is the game engine RHI idea, with dependency rescheduling
The middle layer is the runtime, and the README makes the analogy directly. Like the RHIs in game engines, an abstract runtime layer is introduced to re-unify the fragmented graphics APIs across platforms. It extracts the common concepts and constructs shared by the backend APIs and plays the bridging role between the high-level frontend interfaces and the low-level backend implementations.
The comparison is apt, because that is exactly the role an RHI plays in an engine. DirectX 12, Vulkan and Metal have similar concepts with different names, different object lifetimes and different command submission models, and an RHI is the layer that lets engine code talk to all of them. Here the same layer sits between C++ code and CUDA, DirectX and Metal.
Two things distinguish this runtime from a thin wrapper. The first is the resource wrappers. They are described as high-level resource wrappers to ease programming and eliminate boilerplate code, and they are strongly and statically typed modern C++ objects, which not only simplify the generation of commands via convenient member methods but also support close interaction with the DSL.
The second is the scheduling. With the resource usage information available in kernels and commands, the runtime automatically probes the dependencies between commands and re-schedules them to improve hardware utilisation. That is a systems-level feature rather than a convenience, and it is the kind of thing that only makes sense when the runtime owns the command stream rather than handing it straight to the driver.
The trade is the usual one for a portability layer. Anything the abstraction does not model has to be expressed in terms of what it does model, and the more your workload leans on vendor-specific features, the more the framework's advantage shrinks.
Three working GPU backends and a CPU path rebuilt in Rust
The backends are described as the final realizers of computation. They generate concrete shader sources from the ASTs and compile them into native shaders, they implement the virtual device interfaces with low-level platform-dependent API calls, and they translate the intermediate command representations into native kernel launches and command dispatches.
The current state is specific. There are 3 working GPU backends for the C++ and Python frontends, based on CUDA, Metal and DirectX respectively, and a CPU backend that was re-implemented in Rust for debugging purpose and fallback.
Two things in that sentence matter. The GPU backends are described as working, in a project whose repository topics also list OptiX, RTX, DXR, ISPC, LLVM, Huawei Ascend and SIGGRAPH Asia 2022, which suggests the ambition is wider than the three that ship. And the CPU backend being a rewrite in Rust rather than inherited code tells you it is a debugging and fallback path, not a performance path, and that the project was willing to reimplement a layer in a different language to get the semantics right.
The repository layout shows where the work is. There is an include/ directory for the public headers, src/ for the implementation, examples/ with subdirectories for common, compute, dx, extension, gui, interop, ml, rendering and simulation, plus tutorials/ and docs/ directories and a utils/ directory. The examples are the best documentation of what the framework can actually do, since each of those directories is a working program rather than a snippet.
The Python frontend is early access and does not mirror C++ one to one
Beyond the native C++ DSL and runtime interfaces, the project is also working on a Python frontend, and has published early-access packages to PyPI. The install is a single command.
python -m pip install luisa-pythonPython 3.10 or newer is required, and you can also build your own wheels with pip.
python -m pip wheel <path-to-project> -w <output-dir>Examples using the Python frontend can be found under src/tests/python, and the repository carries build_wheels_linux.sh and build_wheels_macos.sh for producing them, which is a hint that the wheels are built per platform rather than as universal artefacts.
The caveat is stated in the README, and it is the one to read before planning around the Python path. Due to the different syntax and idioms between Python and C++, the Python frontend does not 1:1 reflect the C++ DSL and APIs. The example given is that Python does not have a dedicated reference type qualifier, so the frontend follows the Python idiom that structures and arrays are passed as references.
That is the right way to handle it, and it is also a real difference to plan for. A team that writes the host logic in C++ and prototypes kernels in Python will not be able to move code between the two without translation, which means the Python frontend is best treated as a prototyping and experimentation surface rather than a second implementation of the same code.
The Python package is built with scikit-build-core, CMake and Ninja
The packaging configuration in pyproject.toml is modern and unusual enough to be worth reading, because the version number is derived from the C++ headers rather than from the Python project.
The package is named luisa-python, the build backend is scikit_build_core.build, and the build requirements are pybind11, scikit-build-core at 0.3.2 or above and ninja. The scikit-build section requires CMake 3.28 or newer with a Release build type and the Ninja generator, and pins Ninja at 1.11 or above with make-fallback disabled. The macOS wheel setting expands universal tags, so one wheel covers Apple Silicon and Intel.
The version is the interesting part. The project version is dynamic, and scikit-build is configured with a metadata version provider that reads a regex out of include/luisa/version.h, capturing the LUISA_COMPUTE_VERSION_MAJOR, MINOR and PATCH macros and formatting them as major.minor.patch. The C++ header is the single source of truth for the version, which is the right call for a project whose primary artefacts are C++ libraries and whose Python package is a binding.
The repository also ships two build systems. There is CMakeLists.txt at the root and xmake.lua, and the examples/ directory has its own CMakeLists.txt and xmake.lua, so both generators are supported. BUILD.md, ROADMAP.md, bootstrap.py, a .clang-format, a .clang-tidy and a .clangd configuration, an update_intellisense.lua for editor tooling and a .agents/ directory complete the picture of a project that is set up for a mixed contributor base.
The licence is Apache-2.0 in the repository and BSD in the Python metadata
There is a licensing inconsistency to flag, and it is the kind that a compliance scanner will catch. The repository's own licence, as stated for the framework, is Apache 2.0, and the README carries a badge pointing at the Apache 2.0 text, with a LICENSE file at the repository root.
The Python package metadata in pyproject.toml disagrees. The licence field there is a file reference to the LICENSE file, but the trove classifier reads License :: OSI Approved :: BSD License, and the project description is copied from the paper title. A classifier that says BSD while the file it points to says Apache 2.0 is a mismatch, and it is worth raising with the maintainers rather than guessing which one governs.
For an adopter, the practical guidance is to read the LICENSE file at the repository root, because that is the artefact that covers the code you would be vendoring, and to treat the PyPI classifier as a packaging bug until confirmed otherwise. The Apache-2.0 grant is the permissive end of the scale, with the usual notice and patent-licence terms, and it is compatible with commercial use. This is a licensing fact rather than legal advice.
On maintenance, the signals are good. The repository is not archived, the default branch is stable, and the last push was on 2026-10-15. There are no GitHub releases, which is a little surprising for a project with a paper and a downstream renderer, and it means the version history lives in the git tags and in the ROADMAP.md rather than in a release feed.
Editorial conclusion
LuisaCompute fits a graphics or simulation engineer who has to ship the same kernels to NVIDIA, Apple and Windows hardware and does not want three sets of shader code. It does not fit a project that needs a platform API feature the abstraction does not model, and it does not fit a team that will not maintain a C++ and Python build. Before adopting it, read the ROADMAP.md in the repository, confirm your target backends are the working ones rather than the aspirational ones, and run the examples under examples/compute and examples/rendering on your own hardware to see how much of your existing code survives the abstraction.
Frequently asked questions
What is LuisaCompute and what backends does it support?
It is a high-performance cross-platform computing framework for graphics and beyond, from the group behind the SIGGRAPH Asia 2022 LuisaRender paper. It has 3 working GPU backends for the C++ and Python frontends, based on CUDA, Metal and DirectX, plus a CPU backend re-implemented in Rust for debugging and fallback.
Is the LuisaCompute DSL a separate language?
No. The implementation purely relies on the C++ language itself, without any custom preprocessing pass or compiler extension. Meta-programming simulates the syntax and function and operator overloading trace the kernels, building ASTs that the backends then compile into platform-specific shader source.
How do I install the LuisaCompute Python frontend?
The early-access packages are on PyPI and install with python -m pip install luisa-python, with Python 3.10 or newer required. You can also build wheels yourself with python -m pip wheel, and examples using the Python frontend live under src/tests/python in the repository.
Does the Python frontend match the C++ API?
No. The README states that due to the different syntax and idioms between Python and C++, the Python frontend does not 1:1 reflect the C++ DSL and APIs, and gives the example that Python has no dedicated reference type qualifier, so structures and arrays are passed as references following the Python idiom.
What licence applies to LuisaCompute?
The repository is presented under Apache 2.0, with a LICENSE file at the root and a badge in the README, while the Python package's trove classifier in pyproject.toml reads License :: OSI Approved :: BSD License and points at the same file. The licence file at the repository root is the one to read, since the classifier and the file disagree.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/luisagroup-luisacompute)Was this useful?