Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


pulo

Member Since 23 Jun 2012
Offline Last Active Aug 17 2014 04:56 AM

Posts I've Made

In Topic: Compiling 'ubershader' permutations

23 June 2014 - 05:46 AM

Well it requires some bitwork, ie. shifting and masking. First of all, you'll need to decide yourself the layout of the bits such as

 

bit 0 : Ambient fog (one bit is enough for yes/no)

bit 1 : Normal map 

bit 2-3 : Num Point lights (2 bits is enough for values between 0-3)

bit ... 

 

As the loop counter presents all the shader permutations, only thing left is to extract each bit field (variable "i" is the loop counter presented in the earlier post):

 

bool AmbientFog = i & 1; (the desired value is in the first bit so masking out other bits is enough)

bool NormalMap = (i >> 1) & 1; (the desired value is in the second bit so one shift is necessary and masking after)

int   NumPointLights = (i >> 2) & 3;

...

 

4 bits are used here (you'll need few bits more) so the loop needs to be run 2^4 times. 

 

Shifts are practically multiplies / divisions by 2^(shift value) which effectively will move the bits in the desired positions. After shifting is is necessary to use AND (&) operator to mask out unwanted bits.

 

The loop creating all the permutations doesn't know about the required usage - ie. it can't know whether a permutation is used or not. Nothing prevents you from creating permutations while program is running (and saving them to disk in order to accelerate the program operation). Of course this maybe produce slowdowns if a new shader permuation is required.

 

Cheers!

Do i understand this approach correctly: You compile all the shader permutations in runtime (at startup for example)?

Is it possible to compile the shader permutations in build time, but still having the luxury of having them named nicely, so they can be identified at runtime by using the bitmask you suggested above?


In Topic: Dynamic Shader Linkage and ShaderReflection

23 June 2014 - 04:42 AM

 


How do i get the reflection interface for the default constant buffer?

If you compile your shader with FXC, and then check the output listing for the name of the buffer you should be able to use that name to reflect the constant buffer.  Regarding the performance, I think there is a penalty for using the dynamic linkage (although I've never heard hard numbers on this before).  Most of the systems I have heard of just generate the appropriate shader code and compile the needed variants accordingly.

 

Is that something that isn't a usable solution for you?

 

I also heard about this solution, but could not find any samples or good explanation of whats the best way to go with this kind of system. Do you have any of those at hand?

As i found out about the Dynamic Shader Linkage i was not expecting it being used so rarely, but the explanation from MJP now makes it quite clear why this might be the case. 
 

So: Does anyone have a good article or something about how one would usually go about this kind of system?

 

Thank you for all your input!


In Topic: Dynamic Shader Linkage and ShaderReflection

22 June 2014 - 01:35 PM

Thanks for your answer ;).


Congratulations on being the first person that I've met who's actually trying to use dynamic shader linkage

 

Why is that? Is it to cumbersome, or bad performance wise? I find it a quite interesting idea, especially because it gives you the possibility to create new class instances in run time. 

 


It *might* show up if you get the reflection interface for the default constant buffer, but I'd have to test to find out

 

How do i get the reflection interface for the default constant buffer? I already checked most of the reflection interfaces, including the constant buffers (with GetConstantBufferByIndex()) and bound resources (with GetResourceBindingDesc()). Sadly it does not show up on either of those.

Getting the global interface name by index would be nice, because then one would not have to change the code manually if something changes inside the shader code and it would be easy to "calculate" the offset into the dynamic linkage array.


In Topic: Dynamic Shader Linkage and ShaderReflection

22 June 2014 - 09:22 AM

Well i found something which might help. If i use the GetInterfaceByIndex on the Shader Reflection type i get the expected class "D3D_SVC_INTERFACE_CLASS" which i suspect would be different or non-existent on a normal struct.

 

EDIT: The only thing now left for me is to find out if it is possible to get the name from here through shader reflection. Any Ideas?:

iBaseLight     g_abstractAmbientLighting;
               ^^^^^^^^^^^^^^^^^^^^^^^^

struct PixelInput
{
float4 position : SV_POSITION;
float3 normals : NORMAL;
float2 tex: TEXCOORD0;
};

In Topic: Dynamic Shader Linkage and ShaderReflection

22 June 2014 - 08:47 AM

Yes the constant buffer stays the same, regardless of which class implementation i am using at runtime. (Was this what you were asking?)

The abstract interface is used like this:

iBaseLight     g_abstractAmbientLighting;


struct PixelInput
{
float4 position : SV_POSITION;
float3 normals : NORMAL;
float2 tex: TEXCOORD0;
};


float4 main(PixelInput input) : SV_TARGET
{
float3 Ambient = (float3)0.0f;
Ambient = g_txDiffuse.Sample(g_samplerLin, input.tex) * g_abstractAmbientLighting.IlluminateAmbient(input.normals);


return float4(saturate(Ambient), 1.0f);
}

The reason i would like to reliably differentiate between a normal struct and a class used for dynamic shader linkage is that i would later use the variable name to automatically get the class instances like this: 

 g_pPSClassLinkage->GetClassInstance( varDesc.Name, 0, &g_pAmbientLightClass );

PARTNERS