C# alternative to macros

My code is littered with statements like this

                 case ShaderVariables.WindSpeed:
                        if (fx.Parameters["WindSpeed"] != null)
                            fx.Parameters["WindSpeed"].SetValue(WeatherManager.GetWindSpeed());
                        break;

This is so when I am debugging shaders I can force the output to something.

As most of you know we cannot turn off shader optimization, so changes in the shader source code can lead to shader parameters being optimized away.

This is fine when I am debugging, but I hate having redundant code in release builds, so I would like to remove these checks just for release

I know you could do this…

                     case ShaderVariables.WindSpeed:
#if _DEBUG
                            if (fx.Parameters["WindSpeed"] != null)
#endif
                                fx.Parameters["WindSpeed"].SetValue(WeatherManager.GetWindSpeed());
                            break;

But that is just ugly. :smile:

In C++ it would be easy to define a macro and swap definitions of it, but we don’t have that option in C#

Has anyone come up with a better way of doing it?

This… is… so… frustrating… :smiley:

Anyway, I think what you’re doing might be the easiest solution. Personally though, I don’t like to put those in my code because they’re a real pain to track down sometimes! I think the only thing I might be able to offer is some kind of dependency injection solution where you give it an object that has different behaviour depending on whether or not you’re in debug mode.

Looking at what you have, perhaps an interface called IEffectParameterSetter or something like that so at least it’s reusable for other, similar situations. Then you can have two implementations, one with the if statement (DebugEffectParameterSetter) and the other without (EffectParameterSetter). Probably some kind of factory for creating the appropriate ones and in your program’s entry point, pass the appropriate dependency down or stuff it in a dependency container of some sort and retrieve it where needed.

I mean, it’s kind of like the more testable, maintainable version of a macro anyway… except it also takes a good bit more effort to create :wink:

Sorry I don’t have anything easier!

It’s ugly if it’s all over the place, but what if you put it in a function? Maybe an extension method to the Effect class:

public static void SetParameter(this Effect effect, string name, float value) 
{
#if _DEBUG
    if (effect.Parameters[name] != null)
#endif
        effect.Parameters[name].SetValue(value);
}

and then use it like this:

fx.SetParameter("WindSpeed", windSpeed);

By the way, in newer C# versions you can use the question mark operator to make the if statements look nicer, so this

if (fx.Parameters["WindSpeed"] != null)
    fx.Parameters["WindSpeed"].SetValue(WeatherManager.GetWindSpeed());

becomes this

fx.Parameters["WindSpeed"]?.SetValue(WeatherManager.GetWindSpeed());

If we were only talking about floats, then yes that is a nice clean solution, but we would need vectors matrices ints blah blah blah

The question mark operator is a good solution for this use case , didn’t think of that :smile:

Still doesn’t sort out the basic issue, some way of doing macros in C# would be incredibly useful

I am doing some lisp coding with a friend, and it has brought home to me how much macros can make life easier. Although lisp is a bit of a head feck :confused:

(filter (# (< %0 0)) ‘(1 2 3 -3 -4))

Macros (and static variables inside functions) are the only things I miss from my old C++ times. I understand perfectly that macros are not included into the language, when misused they can bring complete chaos to a project.

Lately I’ve found that local functions are a very nice way to do some stuff I used the macros for. They’re not in any way a substitution for macros, but they help me a lot.

I just do

effect.Parameters["param"]?.SetValue(0f);

Using the ? there will do a null check before continuing. It only does one index lookup instead of the two it does in your code. I would consider this the correct way to do it, the single null check will realistically never impact performance (you’re not setting thousands of parameters per frame) and it gives you the ability to easily modify your shader. You probably wouldn’t want to disable shader optimizations anyway.

1 Like

One option is to write a “pre-processor” or “meta program” that modifies your code before it is compiled (basically just do a find / replace). I think handmade hero shows how you would it in C++ episode 206 if you want an example.

Also I found this built in tool https://www.hanselman.com/blog/T4TextTemplateTransformationToolkitCodeGenerationBestKeptVisualStudioSecret.aspx

I believe the correct way to do this is using functions with the Conditional attribute.
I think an additional pragma inside the function will also reduce the compiled size for Release builds, while not breaking the function call that will ultimately be ignored.

[Conditional("DEBUG")]
public static void AssertTrue(bool b)
{
#if DEBUG
    if (!b)
    {
        throw new Exception();
    }
#endif
}
1 Like