Skip to main content

Workbench

Edit a shader on the left, see it render on the right — instantly.

Workbench: live Slang editing with a rendered viewport and the compiled HLSL side-by-side

Workbench is a small desktop tool for writing shaders and watching them update in real time. You type shader code, and the picture on screen recompiles as you go — no "export, run the compiler, relaunch, look again" loop. It also shows you the compiled output (e.g. HLSL) next to your source, and builds sliders and colour pickers for your shader's parameters automatically.

Heads up — this is a personal side project / experiment. I built it to see how easy a real-time shader-compile loop could feel for artists and TDs. It's Windows / Direct3D 11 only right now, and I may never fully "finish" it. Treat it as a playground and a proof of concept, not a supported product.

New to Slang? Read this first

The shaders here are written in Slang, a modern shader language from NVIDIA, now governed by Khronos. Its big idea is write once, run everywhere: the same shader source can compile to Direct3D (HLSL), Vulkan (SPIR-V), Metal, and WebGPU — so you don't rewrite shaders for every platform.

If you've never touched Slang, this hands-on walkthrough is the friendliest starting point (no prior Slang needed):

📖 Hands-On with Slang: A Practical Tutorial for Graphics Teams — write a simple Slang shader, compile it to Metal / HLSL / SPIR-V from one source, and run it from Python. About 20 minutes end-to-end.

Why that tutorial matters for this project: it shows Slang compiling shaders on demand from a single source. Workbench takes that idea and makes it interactive — instead of running the slangc compiler on the command line each time, it compiles your shader in-process, on every keystroke, and shows the result live. That's the whole experiment: how easy and immediate can shader iteration feel when the compiler is always on. You can also try Slang with zero install in the Slang Playground in your browser.

You don't need to understand the internals below to use Workbench — open it, type in the left panel, and watch the right panel. The rest of this README is for people who want to embed it or build it from source.


For the technically curious: Workbench (distributed on PyPI as miskeyed-workbench, imported as miskeyed.workbench) is a native Qt 6.8 / QRhi Slang shader workbench. Shaders are compiled in-process through Slang's compilation API, rendered with QRhi, and driven by a live, reflection-based parameter UI.

The same C++ Qt objects power three surfaces:

  • the standalone workbench desktop application;
  • a PySide6 tool through Shiboken6 bindings;
  • a DCC or host app that embeds the exposed SlangRhiWidget, ShaderDocument, ShaderParameterModel, or ParameterInspector.

There is no slangc subprocess, no qsb subprocess, and no Python-owned renderer: Qt ownership, signals/slots, parameter buffers, dependency tracking, Slang sessions, and QRhi resources all remain native.

Install

pip install miskeyed-workbench
workbench                 # launch the standalone app
workbench eye.slang       # open a shader on start

Then just start typing in the shader panel — edits recompile and re-render live. Not sure what to type? Try the Slang tutorial or the Slang Playground for shader snippets you can paste in.

Or from Python:

from miskeyed.workbench import WorkbenchWindow

Binary wheels are Windows / Direct3D 11. Building from source needs the Qt 6.8 and Slang SDKs — see Building from source.

Architecture

                         ShaderDocument (QObject)
                                  |
                  +---------------+----------------+
                  |                                |
            DependencyGraph                  SlangCompiler
            live dependency DAG               C++ API only
                  |                                |
        semantic dirty propagation       IGlobalSession / ISession
                  |                                |
       +----------+----------+              Slang reflection
       |          |          |                     |
       v          v          v                     v
    Qt UI      uniform     pipeline       ShaderParameterModel
    only       update      rebuild          dynamic controls
       |          |          |                     |
       +----------+----------+---------------------+
                                  |
                            SlangRhiWidget
                              QRhiWidget
                                  |
                          Direct3D 11 (QRhi)

QRhi is the rendering abstraction, so the Vulkan / Metal / D3D12 backends remain reachable; the shipped build targets Direct3D 11.

Runtime: zero compiler subprocesses

Shader compilation runs through Slang's in-process compilation API:

source buffer
   -> IGlobalSession / ISession
   -> loadModuleFromSourceString()
   -> entry points
   -> link()
   -> getEntryPointCode()
   -> SPIR-V + HLSL + MSL blobs in memory
   -> QShader
   -> QRhiGraphicsPipeline

slangc and qsb are not invoked at runtime.

The Qt 6.8 bridge constructs QShader directly from Slang output. Because QShaderDescription does not expose public mutation APIs for reflection metadata, the bridge is deliberately isolated in Qt68ShaderBridge.cpp and uses Qt's private QShaderDescriptionPrivate. That is acceptable here because QRhi itself already carries Qt-minor-version compatibility constraints. When moving to Qt 6.9/6.10, this file is the compatibility seam.

Dynamic parameter UX

The parameter model is driven by Slang reflection.

Add a numeric global shader parameter:

float pupilDilation;
float corneaIOR;
float3 irisPigment;
bool debugCornea;

After the shader recompiles, ShaderParameterModel reflects the parameter layout and ParameterInspector rebuilds automatically. Existing values are preserved across hot reload when name and type remain compatible.

User-defined Slang attributes (UIRange, UIGroup, UIColor, UIFile, etc.) are exposed through reflection, so ranges and widgets stay shader-owned without comment parsing.

Dependency graph / invalidation model

Invalidation is tracked by a live dependency graph. Each node contains:

  • stable key;
  • node kind;
  • local payload digest;
  • dependency list;
  • Merkle digest;
  • dirty / work flags.

Dependencies are canonicalized by stable key before hashing. The graph is a DAG, so shared shader modules/resources are represented once rather than copied into a tree.

Hash identity and required work are intentionally separate concepts:

ParameterValues changed -> UniformDirty
UiSchema changed        -> UiDirty
Resource changed        -> ResourceDirty
BindingLayout changed   -> BindingDirty + PipelineDirty
Source/Module changed   -> ShaderDirty + PipelineDirty

This keeps common interactions cheap:

slider drag     -> dynamic uniform-buffer update only
texture content -> resource upload only
UI metadata     -> rebuild inspector only
shader body     -> compile affected program/pipeline
binding change  -> rebuild bindings + pipeline

Digests use a 32-byte BLAKE2b implementation matching hashlib.blake2b(..., digest_size=32).

Native C++ API

#include <slang_qrhi/ShaderDocument.h>
#include <slang_qrhi/SlangRhiWidget.h>

using namespace slang_qrhi;   // internal C++ namespace

auto* doc = new ShaderDocument(parent);
doc->setFileUrl(QUrl::fromLocalFile("eye.slang"));
doc->load();
doc->compile();

auto* viewport = new SlangRhiWidget(parent);
viewport->setDocument(doc);
layout->addWidget(viewport);

PySide6 / Shiboken6 API

The Python module exposes the same QObject/QWidget classes:

from miskeyed.workbench import ShaderDocument, SlangRhiWidget, ParameterInspector

self.doc = ShaderDocument(self)
self.doc.fileUrl = QUrl.fromLocalFile("eye.slang")
self.doc.load()

self.viewport = SlangRhiWidget(self)
self.viewport.document = self.doc

self.inspector = ParameterInspector(self)
self.inspector.model = self.doc.parameters

There is no Python mirror of the render core.

Building from source

Requirements:

  • C++20
  • Qt 6.8.x SDK, including private QtGui headers (Qt6::GuiPrivate)
  • PySide6 6.8.x
  • Shiboken6 6.8.x generator
  • Slang SDK (set SLANG_ROOT if CMake cannot find it)
  • Python 3.11+
  • CMake 3.24+

For VFX Platform 2026 deployments, build against the exact Qt/PySide toolchain used by the host DCC.

Shiboken generator

Qt's PyPI shiboken6 package is the runtime module; the generator is distributed by Qt separately. Install the matching generator from Qt's official wheel index before building the Python extension:

python -m pip install `
  --index-url https://download.qt.io/official_releases/QtForPython/ `
  --trusted-host download.qt.io `
  PySide6==6.8.* shiboken6==6.8.* shiboken6_generator==6.8.*

Then point CMake at your Qt 6.8 development SDK and Slang SDK, and build the wheel:

$env:SLANG_ROOT = "C:\sdk\slang"
$env:CMAKE_PREFIX_PATH = "C:\Qt\6.8.3\msvc2022_64"

pip install --no-build-isolation .

Or build the native app directly with CMake:

cmake -S . -B build -G Ninja `
  -DCMAKE_PREFIX_PATH=C:\Qt\6.8.3\msvc2022_64 `
  -DSLANG_ROOT=C:\sdk\slang `
  -DSLANG_QRHI_BUILD_APP=ON
cmake --build build --config Release

Files that matter

cpp/include/slang_qrhi/
    DependencyGraph.h       live dependency DAG + dirty propagation
    ShaderParameterModel.h  reflected GPU parameter model
    ParameterInspector.h    automatic Qt parameter controls
    ShaderDocument.h        source/compile/state coordinator
    SlangRhiWidget.h        embeddable QRhiWidget
    WorkbenchWindow.h       standalone workbench composition

cpp/src/
    SlangCompiler.cpp       in-process Slang API
    Qt68ShaderBridge.cpp    Slang output/reflection -> QShader
    DependencyGraph.cpp     incremental invalidation
    SlangRhiWidget.cpp      QRhi rendering + cheap buffer updates

bindings/
    typesystem_slang_qrhi.xml

app/
    main.cpp                native executable entry point

python/miskeyed/workbench/
    __init__.py             Shiboken module exposure
    __main__.py             `workbench` console entry point

Roadmap

  1. reflect Slang user attributes into ranges/groups/widgets;
  2. resource reflection model (Texture2D, samplers, buffers, HDRI file widgets);
  3. graphics/compute pass graph;
  4. mesh/camera/environment scene helpers;
  5. compile work on a dedicated worker with a long-lived compiler service;
  6. persistent disk cache keyed by the dependency DAG + Slang getEntryPointHash()
    • render state.

License

MIT — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

miskeyed_workbench-0.1.1.tar.gz (653.3 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

miskeyed_workbench-0.1.1-cp313-cp313-win_amd64.whl (50.3 MB view details)

Uploaded CPython 3.13Windows x86-64

miskeyed_workbench-0.1.1-cp312-cp312-win_amd64.whl (50.3 MB view details)

Uploaded CPython 3.12Windows x86-64

miskeyed_workbench-0.1.1-cp311-cp311-win_amd64.whl (50.3 MB view details)

Uploaded CPython 3.11Windows x86-64

File details

Details for the file miskeyed_workbench-0.1.1.tar.gz.

File metadata

  • Download URL: miskeyed_workbench-0.1.1.tar.gz
  • Upload date:
  • Size: 653.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for miskeyed_workbench-0.1.1.tar.gz
Algorithm Hash digest
SHA256 303d11aeb11a0928963b1e34455066cfcf1af015b3a6a92a06a00417a4ea605d
MD5 e95ccc4278675a68d5e60edd20d84a07
BLAKE2b-256 0558613d58eca3e25c68494c803af3e7fdef775cc0c8a17e421bc887701d4954

See more details on using hashes here.

Provenance

The following attestation bundles were made for miskeyed_workbench-0.1.1.tar.gz:

Publisher: release.yml on samjay3d/miskeyed-workbench

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file miskeyed_workbench-0.1.1-cp313-cp313-win_amd64.whl.

File metadata

File hashes

Hashes for miskeyed_workbench-0.1.1-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 c3069ae0d8ac83f8ac012fdc3ca6fcb83063035c37689af3b91b20d2633fe2e0
MD5 80f3a38d237ef65e23d1e49426b181b2
BLAKE2b-256 a7a1a04e11c80e2d05b19706743987d37dd8ce4d790d89b9988a3c1fc0c9b597

See more details on using hashes here.

Provenance

The following attestation bundles were made for miskeyed_workbench-0.1.1-cp313-cp313-win_amd64.whl:

Publisher: release.yml on samjay3d/miskeyed-workbench

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file miskeyed_workbench-0.1.1-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for miskeyed_workbench-0.1.1-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 aa4e6d78a3912481ae9c725e480d62beffbbffb3cbc26f2c409d267ca0a16531
MD5 e413c93680d3f8c72e93b7c7f6ef5481
BLAKE2b-256 fdda6d9c483175481223682e69b5c50dcf1f284c2259ac2520296852685e10a9

See more details on using hashes here.

Provenance

The following attestation bundles were made for miskeyed_workbench-0.1.1-cp312-cp312-win_amd64.whl:

Publisher: release.yml on samjay3d/miskeyed-workbench

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file miskeyed_workbench-0.1.1-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for miskeyed_workbench-0.1.1-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 86e6d42a3dccb779111815c5086b8723f0f050cd4ee386dee24c79e8baad7d74
MD5 c06bb1685cf388e9402847f3402a3c96
BLAKE2b-256 8e1b19bf75742a419fd0c8f45345323ae578878adc6cd9a03f1198fda646ece7

See more details on using hashes here.

Provenance

The following attestation bundles were made for miskeyed_workbench-0.1.1-cp311-cp311-win_amd64.whl:

Publisher: release.yml on samjay3d/miskeyed-workbench

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.3.0

13 files

0.2.1

4 files

0.2.0

4 files

This release

0.1.1 This release

4 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page