How Does HLMS which Shader Template

Discussion area about developing with Ogre-Next (2.1, 2.2 and beyond)


white_waluigi
Goblin
Posts: 253
Joined: Sat Sep 28, 2013 3:46 pm
x 10

How Does HLMS which Shader Template

Post by white_waluigi »

Im currently fighting some mean bugs in my Deferred Shading HLMS and I've decided to start this thing from scratch, since it lets me understand the code better and since this thing works very differently from the oighinal Forward Rendered Approach.
I'm currently trying to figure out how HLMS knows from where to take the Shadercode for the final Shader.
I figured out how it uses Propertys to adress different parts of the Shader but I don't really understand how it finds the FIle PixelShader_ps as an initial starting point.
So how does it do that?
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5433
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1341

Re: How Does HLMS which Shader Template

Post by dark_sylinc »

It's quite simple actually.

On creation you an Ogre::Archive pointer and an array of Ogre::Archive. All of them point to a folder (could also be a Zip... although I never tested that)

The first Ogre::Archive pointer is mandatory.
If it points to C:\MyFolder; then the Hlms will look for C:\MyFolder\PixelShader_ps.hlsl
If the file doesn't exists, it skips that stage (e.g. if PixelShader_ps.hlsl doesn't exist, it gets a null pixel shader; if GeometryShader_gs.hlsl doesn't exist, it gets a null geometry shader). As simple as that.
This logic is in Hlms::createShaderCacheEntry.

You can check the hardcoded names it looks for:

Code: Select all

const String ShaderFiles[] = { "VertexShader_vs", "PixelShader_ps", "GeometryShader_gs",
                               "HullShader_hs", "DomainShader_ds" };
The hlsl/glsl/glsles extension to append is determined in Hlms::_changeRenderSystem.
From this Archive, also pieces will be collected (more about pieces in the next parragraph)

The second argument, the array of Ogre::Archive pointers is only used to gather pieces. The Hlms will look for files in those archives with "piece_vs" in its name; and parse them and collect its pieces to be used in each stage. For example MyCodeSnippets_piece_vs_piece_gs.hlsl will be collected in both the Vertex Shader and Geometry Shader stages.
"piece_all" can be used to collect them in all stages to avoid writing very long and unreadable filenames.

Code: Select all

const String PieceFilePatterns[] = { "piece_vs", "piece_ps", "piece_gs", "piece_hs", "piece_ds" };
The logic for this is in Hlms::enumeratePieceFiles; which happens at startup. Then the collected files (per stage) are parsed in processPieces right before parsing the shader file template.

Originally there was only the first argument. The second argument (the array of Archives) was added later to be able to reuse snippets; since a lot of code was common to many Hlms implementations, so it was a poor practice to copy paste those files over and over again. You can see we've put the common code in "Samples\Media\Hlms\Common"
It also allows users to cleanly customize existing Hlms implementations while storing their custom code in a separate folder (see section 8.6.5 Customizing an existing implementation from the manual; i.e. by defining the piece custom_ps_posMaterialLoad; you can add code that will be executed right after material data was loaded in the pixel shader).
white_waluigi
Goblin
Posts: 253
Joined: Sat Sep 28, 2013 3:46 pm
x 10

Re: How Does HLMS which Shader Template

Post by white_waluigi »

Thanks a lot