• entries
422
1540
• views
492080

# A neat little (ab)use of the C preprocessor

185 views

Earlier this week I posted about a really obscure slow-down in my D3D application. I've now found out what seems to be causing it, but I still dont really understand the why [headshake]

I was missing it because I'd set VStudio to filter debug output and avoid module/thread/process messages (they usually just clutter things up). Turns out that making copies of the implicit swap-chain is causing the VC runtime (or VStudio debugger) to spawn lots of threads. I mean LOTS of threads.

If I enable "Thread Exit Messages" then I get several "Thread 0xABCD has exited" type messages for every single frame. They go away if I comment out the defensive copying of the implicit swap chain. I have no idea what that about - seems to be a VStudio thing as the DX debug runtimes dont make a sound about it and it only happens with a debug build of my code.

Not really sure where to go with this one - I'll probably have to dig into the debugger to try and find a way of identifying what all those threads are doing [oh]

I was chatting with circlesoft yesterday about various things, one of them was a trick I'd found for converting enumeration constants into their respective symbolic name.

Check out the screenshot in this reply. A couple of the debug lines decode the state value to be DMAPOFFSET whereas the rest are the "raw" integer values that you're probably familiar with. This trick allows you to convert those raw integer values into their text/symbolic name.

I knocked this together to help with some D3D10 debugging - I could use shader reflection to determine inputs and get a '0' for the D3D10_SHADER_INPUT_TYPE value. The following trick will then convert that '0' integer value into the string L"D3D10_SIT_CBUFFER" - perfect for sending to the debug output or a log file [grin]

You might think it requires an awful lot of tedious copy-n-paste "coding". It doesn't and is, in fact, extremely quick and easy:

Use this definition:

#define ENUM_AS_STRING( wc, len, v ) case v: wcscpy_s( (wc), (len), L## #v ); break;

How to use:

typedef enum _D3D10_SHADER_INPUT_TYPE{    D3D10_SIT_CBUFFER,    D3D10_SIT_TBUFFER,    D3D10_SIT_TEXTURE,    D3D10_SIT_SAMPLER,} D3D10_SHADER_INPUT_TYPE, *LPD3D10_SHADER_INPUT_TYPE;

2. Delete top/bottom parts and add switch():

switch( value ){    D3D10_SIT_CBUFFER,    D3D10_SIT_TBUFFER,    D3D10_SIT_TEXTURE,    D3D10_SIT_SAMPLER,}

3. Do find-n-replace:
find: "D3D10_SIT_"
replace: "ENUM_AS_STRING( wc, length, D3D10_SIT_"
Generates:
switch( value ){    ENUM_AS_STRING( wc, length, D3D10_SIT_CBUFFER,    ENUM_AS_STRING( wc, length, D3D10_SIT_TBUFFER,    ENUM_AS_STRING( wc, length, D3D10_SIT_TEXTURE,    ENUM_AS_STRING( wc, length, D3D10_SIT_SAMPLER,}

4. find-n-replace again:
find: ","
replace: " )"
Generates:
switch( value ){    ENUM_AS_STRING( wc, length, D3D10_SIT_CBUFFER )    ENUM_AS_STRING( wc, length, D3D10_SIT_TBUFFER )    ENUM_AS_STRING( wc, length, D3D10_SIT_TEXTURE )    ENUM_AS_STRING( wc, length, D3D10_SIT_SAMPLER )}

5. done! Similar variants using wildcards can be used for enums with specific values (e.g. x = 1, y = 2, z = 4 etc..)

Now I'd imagine very few people will want to use D3D10 enumerations for this, but the exact same trick works fine for pretty much any enum (even custom ones). I've got similar code that'll decode a D3DFORMAT value into its corresponding symbolic name.

Remember I had that issue with the debug runtimes creating loads of threads to create textures? I found yesterday it creats 4 threads per mip-level. And I still don't know what's causing it. I'll try to remember to post on the DX mailing list when I get home.

I was thinking about bugging you for some information on the threads - I do indeed remember your similar problem [smile]

I've probably got the DXDev emails archived on my other machine, so I'll have a dig around as well. Any extra info you have would be great though!

Cheers,
Jack

## Create an account

Register a new account