5
\$\begingroup\$

Is it possible to use project level conditional defines in hlsl code?

I'm trying to conditionaly compile a shader using MonoGame Content Procesor. Depending on project type (ie. Windows, Windows8...) different shader models should be used. Pragma directives are supported. The code:

#if WINDOWS 
   PixelShader = compile ps_3_0 PixelShaderFunction();
#else 
   ...

... doesn't work as WINDOWS is interpreted as false. Judging from the article on Gamasutra this should work. This answer on Gamedev lists constants which should be defined when using MonoGame.

I've also tried adding constants into csproj manually (in content project, then in dummy content compiler csproj).

Is there something I'm missing?

My sln structure is as follows:

  1. MonoGameContentProject - holds .fx file
  2. MonoGameDummyProject - has content reference to content project, builds .fx file
  3. WindowsProject - has a link to dummy project xnb file in the windows build directory
\$\endgroup\$
6
  • 1
    \$\begingroup\$ try #if WIN32 \$\endgroup\$
    – OMGtechy
    Commented Jul 21, 2014 at 14:53
  • \$\begingroup\$ Do you have the WINDOWS flag set for your project? The flags listed in your GDSE link are set as part of the compilation setting of the MonoGame projects and are not set in your project unless you add them to your projects compilation settings. \$\endgroup\$ Commented Jul 21, 2014 at 14:55
  • \$\begingroup\$ @OMGtechy sadly it doesn't work as well \$\endgroup\$
    – Goran
    Commented Jul 21, 2014 at 17:05
  • \$\begingroup\$ @ClassicThunder In which project should that be? The content, dummy or the game project (I've edited my question and added my sln structure) \$\endgroup\$
    – Goran
    Commented Jul 21, 2014 at 17:06
  • \$\begingroup\$ Do you mind uploading a minimalistic project that has the issue? \$\endgroup\$ Commented Jul 24, 2014 at 18:04

2 Answers 2

2
\$\begingroup\$

Mono should behave the same way as .Net and the MSDN has this to say on preprocessor instructions ...

When the C# compiler encounters an #if directive, followed eventually by an #endif directive, it will compile the code between the directives only if the specified symbol is defined. Unlike C and C++, you cannot assign a numeric value to a symbol; the #if statement in C# is Boolean and only tests whether the symbol has been defined or not.

So it may be that the #define WINDOWS definition has not been made yet. I'm looking to see if I can find something useful on this.

Interesting secondary point but not really what you are after ...

https://stackoverflow.com/questions/473354/quote-needed-preprocessor-usage-is-bad-oo-practice

Could you perhaps take another approach?

Possible solution: Your syntax may not be quite right try something like this ...

#if (WINDOWS)
  // some WINDOWS-specific code here
#endif

EDIT: In light of my missing the fact that this is a shader problem I figured I should add this ...

Conditional defines based on environments are only possible on the CPU, to have such differences in shaders you need to create different versions of your shaders then conditionally choose them in your CPU code in which situation the above syntax should work.

In short: such preprocessor instructions are not possible in shader code.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ The defines given to the C# compiler are almost certainly not passed on to the HLSL compiler. As it is completely unrelated to C# or .NET. \$\endgroup\$
    – Roy T.
    Commented Jul 30, 2014 at 16:20
  • \$\begingroup\$ thats true, i hadnt noticed that subtle syntax difference. That measn the solution is to compile a different shader rather than trying to put this condition in the shader code. \$\endgroup\$
    – War
    Commented Jul 30, 2014 at 21:48
  • \$\begingroup\$ I think so too - the article from Gamasutra has led me in the wrong direction as it clearly demonstrates the use of confitional defines in HLSL compiler. I guess the issue can be solved using #include and HLSL fragments but I was hoping for something simpler. \$\endgroup\$
    – Goran
    Commented Jul 31, 2014 at 8:38
0
\$\begingroup\$

I don't think you can directly, but you might consider writing a simple preprocessor and creating a custom build step.

\$\endgroup\$
1
  • \$\begingroup\$ ouch !! overkill !! f he has to go that far I wouldn't use pre processor instructions at all I would have versioning in my types to pick the right components to init ... maybe using dependency injection or something ... if he followed a naming convention this could be fairly swish. \$\endgroup\$
    – War
    Commented Jul 27, 2014 at 20:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .