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.2.0.tar.gz (659.8 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.2.0-cp313-cp313-win_amd64.whl (50.9 MB view details)

Uploaded CPython 3.13Windows x86-64

miskeyed_workbench-0.2.0-cp312-cp312-win_amd64.whl (50.9 MB view details)

Uploaded CPython 3.12Windows x86-64

miskeyed_workbench-0.2.0-cp311-cp311-win_amd64.whl (50.9 MB view details)

Uploaded CPython 3.11Windows x86-64

File details

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

File metadata

  • Download URL: miskeyed_workbench-0.2.0.tar.gz
  • Upload date:
  • Size: 659.8 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.2.0.tar.gz
Algorithm Hash digest
SHA256 36e5d31e914e10122a36b93855abdb13be0626cb6d5e7a6662d249a34e2c5e36
MD5 ab907c374a41b9731a49a45f89941683
BLAKE2b-256 27b93a9c22302266d8c5904889804dcc6e5b4f68c65462c5e4160147d15d2bfd

See more details on using hashes here.

Provenance

The following attestation bundles were made for miskeyed_workbench-0.2.0.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.2.0-cp313-cp313-win_amd64.whl.

File metadata

File hashes

Hashes for miskeyed_workbench-0.2.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 4988b1695a729cc020f8cda246d54dcc62e4f8df4e0ca2b00da63455edfea588
MD5 948e029093d7a8c74e12722f7ea1a774
BLAKE2b-256 d0d1d8ace3885c03a4a70a860ec3f1316efdacb976879cb3652f1e769eb5bb90

See more details on using hashes here.

Provenance

The following attestation bundles were made for miskeyed_workbench-0.2.0-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.2.0-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for miskeyed_workbench-0.2.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 3f4b1b75311147142c4208db7e9276dd33c8874407fcd8cdbc007cd54058baff
MD5 cf9b8b35d6409ac6e19f12c23928e1e1
BLAKE2b-256 a7ef40a2b5e13388cba8f7b13501baea6aa162f23dd4189a7a70e37ebbc554fc

See more details on using hashes here.

Provenance

The following attestation bundles were made for miskeyed_workbench-0.2.0-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.2.0-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for miskeyed_workbench-0.2.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 126c286bd04696b48581ad7d85ba8aa7d9867440c5577e22060850fe50dddb86
MD5 22d17dc0cb3983489b3a98bed9e6ced3
BLAKE2b-256 78c1b2e3b4302bb2402f6a092d33b9d0a25784ffb0aa0a4bd58304016753c496

See more details on using hashes here.

Provenance

The following attestation bundles were made for miskeyed_workbench-0.2.0-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

This release

0.2.0 This release

4 files

0.1.1

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