shader
Runtime shader compilation: baking GLSL, the on-disk artifact cache, DXIL for Direct3D, and SPIR-V linking.
| Group | shader |
Detailed description
libshader bakes a GLSL source into a QShader and keeps the result in shader::ArtifactCache, so the same source does not bake again on the next run of the same version. It parses the glslang diagnostics for the shader editor. On Windows it attaches a DXIL blob compiled with DXC, so the Direct3D 12 backend never runs FXC. It also links per-module SPIR-V, parses the tracer records, and probes the gradient of a distance field.
libconstruct and libpaint use it.
Function documentation
dxcCompileMutex
std::mutex &shader::dxcCompileMutex()
One DXC compile at a time, process-wide.
`dxcompiler.dll` is entered from at least four threads in this application — the GUI thread, the render worker, the thumbnail worker and N compile-pool threads — and nothing serialized them. DXC's `DxcCreateInstance` hands every caller the library's own global allocator, and that allocator is not thread-safe; concurrent compiles corrupt its heap.
That is not a theory. On mathilde64 a field run died with `0xC0000374`, "a heap has been corrupted", raised by `RtlFreeHeap` under `dxcompiler!DxcDelete` and `clang::CompilerInstance::~CompilerInstance`, on the render worker, while the compile pool was building the deferred pipelines (windows-field-defects §WFD-RL-32.6). The app showed "not responding" for as long as Windows took to write a 3.6 GB dump.
The cost is that shader compiles no longer overlap. They are already off the GUI thread and cached on disk, so the cost is paid once per distinct shader and never on the interactive path. A corrupted heap is not a trade against throughput.