Advertisement

Automated debug GUI for shader constants

Started by November 24, 2017 06:29 PM
3 comments, last by knarkowicz 7 years, 2 months ago

Looking for some advice.

I have a toy graphics framework I use for experimenting and the vast majority of the time I spend is on tweaking/debugging shaders. And a big part of that involves tweaking constants and other options to get the look or effect right or to just debug problems. Right now my process looks like this:

1. Add variable(s) to "material debug" cbuffer in hlsl.
2. Add variable(s) to mirrored C++ struct that I use to update the constant buffer (while being careful not to break alignment/padding requirements)
3. Add entries into debug gui
4. Fix inevitable copy/paste errors

Has anyone found a satisfactory combination of build pipeline, code generation, reflection or otherwise that could automate some or all this?

I suppose another option is to quit the reliance on on screen gui and instead implement some form of shader reloading so I can edit constants directly in hlsl.

[size=2]

I use code-gen for my own experimental framework. I write a C# file that contains a few classes, where each class represents group of settings. These settings use custom attributes to add additional UI parameters, like descriptions and min/max values. This file is processed by a small C# app that I call "SettingsCompiler", which invokes the C# compiler to compile the .cs file containing the settings. Once compiled into an assembly, the settings and their attributes are reflected by the settings compiler and pulled into a list. From there, the settings compiler generates C++ code for initializing the settings using my framework's runtime classes. It also generates a matching HLSL file containing the constant buffer layout, as well as C++ code for filling that constant buffer with the current settings values.

The whole thing took a while to set up, but it's definitely worth the time savings now that I don't have to manually add and remove UI + cbuffer definitions. I was able to get it integrated nicely into a VS solution so that the SettingsCompiler is invoked as a custom build step right before the C++ code is compiled, so it's pretty transparent. I also rarely mess with that code now that it's working.

If you want to have a look at my implementation, it's all up on GitHub under the MIT license. The older version that uses D3D11 and AntTweakBar is here, and the newer version that uses D3D12 and ImGui is here.

Even if you go down the code-gen route, I would still recommend getting basic shader reloading to work. It's really nice being able to make quick changes and have them re-load without having to re-start the app. It's also not too hard to get going with basic timestamps. A lot of people will go down the path of using the Windows file watching API's for doing this, which certainly works but can be a real PITA to get right. But if you only have a few files to monitor, then you can just brute force it by checking the file timestamps occasionally. 

Advertisement

Yeah shader reloading is a must have feature :D

I don't have a generic material tweaking GUI, but I think you've inspired me to hook one up. 

I've got reflection data on all my cbuffers already, which was pretty easy to set up. I use FXC to pre-compile my shaders, and you can use some command line arguments to tell it to output the shader binary, but also output a human readable report on the ASM and resource bindings to a different file. I parse that report with some regexs to build my reflection data, and save it alongside the shader binaries. 

I already use the reflection data at runtime so that variables can be set by name, and it would be pretty straightforward to iterate through all the cbuffers members and generate a slider/etc widget for each of them. 

We have a very simple workflow at work: shader reloading and a global cbuffer with some debug params. Global cbuffer is attached to every shader and includes debug params, which can be controlled by UI (sliders, color picker etc.) and console commands. When you want to test something inside a shader, you just replace some variable with a debug var and you are ready to toggle changes with a keyboard shortcut (bind key to a console command) or play with a value using a slider or color picker.

This topic is closed to new replies.

Advertisement