[2.1] Adding HLMS customisations per datablock
-
- OGRE Expert User
- Posts: 1227
- Joined: Thu Dec 11, 2008 7:56 pm
- Location: Bristol, UK
- x 157
[2.1] Adding HLMS customisations per datablock
Me again
I know adding some form of interface or callback system to allow customisations per Renderable would be a very bad idea, however I have been looking at ways to be able to add customisations per datablock, without changing any Ogre code.
So, you can add custom piece files that will be parsed based on what properties are set, so my question is could we have custom properties per datablock which could be set from a material file, this would affectively allow (along with custom piece files) customisations per renderable.
I am sure I have missed something critical, potentially render queue sorting assumptions, but any thoughts!?
I know adding some form of interface or callback system to allow customisations per Renderable would be a very bad idea, however I have been looking at ways to be able to add customisations per datablock, without changing any Ogre code.
So, you can add custom piece files that will be parsed based on what properties are set, so my question is could we have custom properties per datablock which could be set from a material file, this would affectively allow (along with custom piece files) customisations per renderable.
I am sure I have missed something critical, potentially render queue sorting assumptions, but any thoughts!?
-
- OGRE Team Member
- Posts: 5436
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1343
Re: [2.1] Adding HLMS customisations per datablock
As for making the changes per Datablock:
At shader level: I realize there is no custom_ps_ piece for adding more data. This can be easily be fixed.
At C++ level: I don't think a listener is a good idea. It wouldn't be clean and would be complicated. The best method I see is deriving from both HlmsPbs and HlmsPbsDatablock:
A small modification to Ogre would be required so that ConstBufferPool() gets the HlmsMyDatablock::MaterialSizeInGpuAligned instead of HlmsPbsDatablock::MaterialSizeInGpuAligned.
And then you're set.
As for making the changes per Renderable:
Again, no listener, this time the reason is performance. But this time it involves overloading HlmsPbs::fillBuffersFor so we can send more information via mCurrentMappedConstBuffer or mCurrentMappedTexBuffer.
This method is the biggest of all (in terms of lines of code and work being done), so overloading it could involve a lot of copy pasting. It's definitely the most intrusive / less modular section; and the most difficult to maintain if the original codebase in the repo changes (however, it has been very stable by now).
At shader level: I realize there is no custom_ps_ piece for adding more data. This can be easily be fixed.
At C++ level: I don't think a listener is a good idea. It wouldn't be clean and would be complicated. The best method I see is deriving from both HlmsPbs and HlmsPbsDatablock:
Code: Select all
class HlmsMyDatablock : public HlmsPbsDatablock
{
//Override what we send to the GPU (usually to send [i]more[/i] data)
virtual void uploadToConstBuffer( char *dstPtr );
}
class HlmsMy : public HlmsPbs
{
//Override to return a HlmsMyDatablock.
virtual HlmsDatablock* createDatablockImpl( IdString datablockName,
const HlmsMacroblock *macroblock,
const HlmsBlendblock *blendblock,
const HlmsParamVec ¶mVec );
}
And then you're set.
As for making the changes per Renderable:
Again, no listener, this time the reason is performance. But this time it involves overloading HlmsPbs::fillBuffersFor so we can send more information via mCurrentMappedConstBuffer or mCurrentMappedTexBuffer.
This method is the biggest of all (in terms of lines of code and work being done), so overloading it could involve a lot of copy pasting. It's definitely the most intrusive / less modular section; and the most difficult to maintain if the original codebase in the repo changes (however, it has been very stable by now).
-
- OGRE Team Member
- Posts: 5436
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1343
Re: [2.1] Adding HLMS customisations per datablock
If Renderable A has properties x, y & z set; and renderables B, C, D have properties y & z set; BCD will be sorted together, A will be sorted to be rendered after or before BCD (unless they are transparent, in which case distance to camera takes precedence)al2950 wrote:I am sure I have missed something critical, potentially render queue sorting assumptions, but any thoughts!?
If each renderable has a different set of properties (i.e. you have a property that is set to the value of movableObject->getId()); that would be very bad (each Renderable gets its own shader, and can't be batched together).
As for fillBuffersFor; issuing a command (via CommandBuffer::addCommand) inside this function breaks (splits) auto instancing. If you issue a command for every Renderable, there won't be any instancing being done.
-
- OGRE Expert User
- Posts: 1227
- Joined: Thu Dec 11, 2008 7:56 pm
- Location: Bristol, UK
- x 157
Re: [2.1] Adding HLMS customisations per datablock
OK, I think I understand all. But just to give it some context for others here is an example
I am adding some wet surface code to the shaders as I discussed here;
http://ogre3d.org/forums/viewtopic.php?f=25&t=84774
Ideally I want to add a 'porosity' property to each material. Doing this via the hlms properties is a bad idea, as it would effectively create a different shader for every different 'porisity' value, which would in turn heavily hinder ogre's ability to auto instance and reduce draw calls?? This should be done by adding an extra data value to the const material buffers, which will require overriding the base PBS implementation.
I think I have got that correct, please let me know if not.
I am adding some wet surface code to the shaders as I discussed here;
http://ogre3d.org/forums/viewtopic.php?f=25&t=84774
Ideally I want to add a 'porosity' property to each material. Doing this via the hlms properties is a bad idea, as it would effectively create a different shader for every different 'porisity' value, which would in turn heavily hinder ogre's ability to auto instance and reduce draw calls?? This should be done by adding an extra data value to the const material buffers, which will require overriding the base PBS implementation.
I think I have got that correct, please let me know if not.
-
- OGRE Team Member
- Posts: 5436
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1343
Re: [2.1] Adding HLMS customisations per datablock
You are correct on all accounts.
Of course if you only think there will be only 3 or 4 different porosity values, you can choose to embed it as a property as the impact won't be noticeable. But if you have far too many, you'll be hindering our ability to auto instance greatly.
Of course if you only think there will be only 3 or 4 different porosity values, you can choose to embed it as a property as the impact won't be noticeable. But if you have far too many, you'll be hindering our ability to auto instance greatly.
-
- OGRE Contributor
- Posts: 267
- Joined: Wed Apr 23, 2014 3:49 pm
- Location: Bologna, Italy
- x 75
Re: [2.1] Adding HLMS customisations per datablock
I'm resuming this old thread for asking this.dark_sylinc wrote: As for making the changes per Datablock:
At shader level: I realize there is no custom_ps_ piece for adding more data. This can be easily be fixed.
Is it possible to add a @insertpiece( custom_materialBuffer ) (or something similar) in the Material struct declaration?
Senior programmer at 505 Games; former senior engine programmer at Sandbox Games
Worked on: Racecraft Esport — Racecraft Coin-Op, Victory: The Age of Racing
-
- OGRE Expert User
- Posts: 1148
- Joined: Sat Jul 06, 2013 10:59 pm
- Location: Chile
- x 169
Re: [2.1] Adding HLMS customisations per datablock
hello!!! Posible feature request:
I need to set some custom values per datablock, and I noticed that there is an interesting
that could be renamed to:
and add a setter/getter:
and then in my custom pieces I can do:
to read my values =D
this would be very useful, any reason why has not done before? why is this reserved?
thanks!
I need to set some custom values per datablock, and I noticed that there is an interesting
Code: Select all
float mReserved[3][4];
Code: Select all
float mUserValues[3][4];
Code: Select all
void HlmsPbsDatablock::setUserValue( uiont_8, index, Ogre::Vector3 value )
Code: Select all
material.userValue[i].xyzw
this would be very useful, any reason why has not done before? why is this reserved?
thanks!
-
- OGRE Team Member
- Posts: 5436
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1343
Re: [2.1] Adding HLMS customisations per datablock
Not entirely a bad idea.
The thing is, 256-bytes per material has measurable higher performance thus that's why they're reserved. We may have more settings in the future but I can't remember exactly why.
I'm a little occupied now to do it myself so PRs to implement this are welcome.
The thing is, 256-bytes per material has measurable higher performance thus that's why they're reserved. We may have more settings in the future but I can't remember exactly why.
I'm a little occupied now to do it myself so PRs to implement this are welcome.
-
- OGRE Expert User
- Posts: 1148
- Joined: Sat Jul 06, 2013 10:59 pm
- Location: Chile
- x 169
Re: [2.1] Adding HLMS customisations per datablock
thanks! I will PR, I was just looking on how to do PRs =D, expect one soon
-
- OGRE Expert User
- Posts: 1148
- Joined: Sat Jul 06, 2013 10:59 pm
- Location: Chile
- x 169
Re: [2.1] Adding HLMS customisations per datablock
pull request up! https://bitbucket.org/sinbad/ogre/pull-requests/818
I hope I did it well =D
I also added custom_vs_preTransform to the vertex shaders, something I use in my custom pieces to make wind movement effect, might be useful for someone else.
Saludos!
I hope I did it well =D
I also added custom_vs_preTransform to the vertex shaders, something I use in my custom pieces to make wind movement effect, might be useful for someone else.
Saludos!
-
- OGRE Expert User
- Posts: 1148
- Joined: Sat Jul 06, 2013 10:59 pm
- Location: Chile
- x 169
Re: [2.1] Adding HLMS customisations per datablock
Hello! I need to make a dynamic displace map in just a specific object, but maintaining all the pbs features, so... since there's is no way to add a custom texture to the vertex shader to a specific datablock I just did this:
yHlmsPbsExtended.cpp:
.h:
and yHlmsPbsDatablockExtended.cpp:
.h:
and the corresponding @property( "displace_map" ) in the vertex shader:
and it was working!!! until yesterday that I updated Ogre to the current version, (I was using a version from many months ago)
I think that I am doing something wrong and it was working just by luck before... or there is something broken in the current version?
the @property is working, it is entering the right parts of the Hlms code, but in the vertex shader I don't get the texture, there might be a binding problem
this is my code:dark_sylinc wrote: ↑Wed Jan 27, 2016 10:22 pm .......
The best method I see is deriving from both HlmsPbs and HlmsPbsDatablock:
.......
yHlmsPbsExtended.cpp:
Code: Select all
#include "yHlmsPbsExtended.h"
#include "yHlmsPbsDatablockExtended.h"
#include "OgreRoot.h"
#include "OgreHlmsManager.h"
#include "CommandBuffer/OgreCommandBuffer.h"
#include "CommandBuffer/OgreCbTexture.h"
#include "CommandBuffer/OgreCbShaderBuffer.h"
#include "OgreTextureManager.h"
#include <iostream>
yHlmsPbsExtended::yHlmsPbsExtended( Ogre::Archive *dataFolder, Ogre::ArchiveVec *libraryFolders ) :
HlmsPbs( dataFolder, libraryFolders )
{
Ogre::HlmsSamplerblock samplerblock;
samplerblock.mU = Ogre::TextureAddressingMode::TAM_CLAMP;
samplerblock.mV = Ogre::TextureAddressingMode::TAM_CLAMP;
samplerblock.mW = Ogre::TextureAddressingMode::TAM_CLAMP;
samplerblock.mMaxAnisotropy = 8;
samplerblock.mMagFilter = Ogre::FO_ANISOTROPIC;
mSamplerblockWrap = Ogre::Root::getSingleton().getHlmsManager()->getSamplerblock(samplerblock);
}
const Ogre::HlmsCache* yHlmsPbsExtended::createShaderCacheEntry( Ogre::uint32 renderableHash,
const Ogre::HlmsCache &passCache,
Ogre::uint32 finalHash,
const Ogre::QueuedRenderable &queuedRenderable )
{
const Ogre::HlmsCache* retVal = HlmsPbs::createShaderCacheEntry( renderableHash, passCache, finalHash, queuedRenderable );
const bool useDisplaceTexture = getProperty( "displace_map" ) != 0;
Ogre::GpuProgramParametersSharedPtr vsParams = retVal->pso.vertexShader->getDefaultParameters();
if( useDisplaceTexture ){
vsParams->setNamedConstant( "displaceMap", 13 );
}
mRenderSystem->bindGpuProgramParameters( Ogre::GPT_VERTEX_PROGRAM, vsParams, Ogre::GPV_ALL );
return retVal;
}
void yHlmsPbsExtended::calculateHashForPreCreate( Ogre::Renderable *renderable, Ogre::PiecesMap *inOutPieces ){
HlmsPbs::calculateHashForPreCreate( renderable, inOutPieces );
assert( dynamic_cast<yHlmsPbsDatablockExtended*>( renderable->getDatablock() ) );
yHlmsPbsDatablockExtended *datablock = static_cast<yHlmsPbsDatablockExtended*>(
renderable->getDatablock() );
if( !datablock->getDisplaceTexture().isNull() ){
setProperty( "displace_map", 1 );
}
}
Ogre::uint32 yHlmsPbsExtended::fillBuffersForV2( const Ogre::HlmsCache *cache,
const Ogre::QueuedRenderable &queuedRenderable,
bool casterPass, Ogre::uint32 lastCacheHash,
Ogre::CommandBuffer *commandBuffer )
{
Ogre::uint32 retVal = HlmsPbs::fillBuffersForV2( cache, queuedRenderable, casterPass, lastCacheHash, commandBuffer );
assert( dynamic_cast<const yHlmsPbsDatablockExtended*>( queuedRenderable.renderable->getDatablock() ) );
const yHlmsPbsDatablockExtended *datablock = static_cast<const yHlmsPbsDatablockExtended*>(
queuedRenderable.renderable->getDatablock() );
if( OGRE_EXTRACT_HLMS_TYPE_FROM_CACHE_HASH( lastCacheHash ) != mType )
{
if( !datablock->getDisplaceTexture().isNull() ){
const Ogre::TexturePtr &displaceTex = datablock->getDisplaceTexture();
*commandBuffer->addCommand<Ogre::CbTexture>() = Ogre::CbTexture( 13, true, displaceTex.get(), mSamplerblockWrap );
}
}
return retVal;
}
Ogre::HlmsDatablock* yHlmsPbsExtended::createDatablockImpl( Ogre::IdString datablockName,
const Ogre::HlmsMacroblock *macroblock,
const Ogre::HlmsBlendblock *blendblock,
const Ogre::HlmsParamVec ¶mVec )
{
return OGRE_NEW yHlmsPbsDatablockExtended( datablockName, this, macroblock, blendblock, paramVec );
}
Code: Select all
#ifndef YHLMSPBSEXTENDED_H
#define YHLMSPBSEXTENDED_H
#include "OgreHlmsPbs.h"
class yHlmsPbsDatablockExtended;
class yHlmsPbsExtended : public Ogre::HlmsPbs
{
public:
yHlmsPbsExtended( Ogre::Archive *dataFolder, Ogre::ArchiveVec *libraryFolders );
const Ogre::HlmsCache* createShaderCacheEntry( Ogre::uint32 renderableHash,
const Ogre::HlmsCache &passCache,
Ogre::uint32 finalHash,
const Ogre::QueuedRenderable &queuedRenderable ) override;
void calculateHashForPreCreate( Ogre::Renderable *renderable, Ogre::PiecesMap *inOutPieces ) override;
Ogre::uint32 fillBuffersForV2( const Ogre::HlmsCache *cache,
const Ogre::QueuedRenderable &queuedRenderable,
bool casterPass, Ogre::uint32 lastCacheHash,
Ogre::CommandBuffer *commandBuffer ) override;
Ogre::HlmsDatablock* createDatablockImpl( Ogre::IdString datablockName,
const Ogre::HlmsMacroblock *macroblock,
const Ogre::HlmsBlendblock *blendblock,
const Ogre::HlmsParamVec ¶mVec ) override;
const Ogre::HlmsSamplerblock* mSamplerblockWrap;
};
#endif // YHLMSPBSEXTENDED_H
Code: Select all
#include "yHlmsPbsDatablockExtended.h"
#include <iostream>
yHlmsPbsDatablockExtended::yHlmsPbsDatablockExtended( Ogre::IdString name, Ogre::HlmsPbs *creator,
const Ogre::HlmsMacroblock *macroblock,
const Ogre::HlmsBlendblock *blendblock,
const Ogre::HlmsParamVec ¶ms ) :
Ogre::HlmsPbsDatablock( name, creator, macroblock, blendblock, params )
{
mDisplaceTexture.setNull();
}
void yHlmsPbsDatablockExtended::setDisplaceTexture( Ogre::TexturePtr texture ){
mDisplaceTexture = texture;
}
const Ogre::TexturePtr &yHlmsPbsDatablockExtended::getDisplaceTexture() const{
return mDisplaceTexture;
}
Code: Select all
#ifndef YHLMSPBSDATABLOCKEXTENDED_H
#define YHLMSPBSDATABLOCKEXTENDED_H
#include "OgreHlmsPbsDatablock.h"
class yHlmsPbsDatablockExtended : public Ogre::HlmsPbsDatablock
{
friend class yHlmsPbsExtended;
public:
yHlmsPbsDatablockExtended( Ogre::IdString name, Ogre::HlmsPbs *creator,
const Ogre::HlmsMacroblock *macroblock,
const Ogre::HlmsBlendblock *blendblock,
const Ogre::HlmsParamVec ¶ms );
void setDisplaceTexture( Ogre::TexturePtr texture );
const Ogre::TexturePtr &getDisplaceTexture() const;
private:
Ogre::TexturePtr mDisplaceTexture;
};
#endif // YHLMSPBSDATABLOCKEXTENDED_H
Code: Select all
@property( displace_map )
uniform sampler2DArray displaceMap[1]; //yes! the texture is TEX_TYPE_2D_ARRAY for no real reason
@end
.....
@property( displace_map )
worldPos.xyz += ( vec4( @insertpiece(local_normal) * texture( displaceMap[0], vec3( uv0, 0 ) ).x*0.1, 0 ) * worldMat ).xyz ;
@end
I think that I am doing something wrong and it was working just by luck before... or there is something broken in the current version?
the @property is working, it is entering the right parts of the Hlms code, but in the vertex shader I don't get the texture, there might be a binding problem
-
- OGRE Team Member
- Posts: 5436
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1343
Re: [2.1] Adding HLMS customisations per datablock
Does this work as expected?
We may have accidentally cleaned up the properties thus it may always be returning false (just a guess)
Another possibility is that binding slot "13" is now too small if your material uses many textures and there were more slots added.
If RenderDoc is showing you that the code is generated correctly, then it could be indeed a binding problem.
If you have spare computing power to recompile Ogre several times, try using hg bisect to find when it broke in no time.
Code: Select all
const bool useDisplaceTexture = getProperty( "displace_map" ) != 0;
Another possibility is that binding slot "13" is now too small if your material uses many textures and there were more slots added.
If RenderDoc is showing you that the code is generated correctly, then it could be indeed a binding problem.
If you have spare computing power to recompile Ogre several times, try using hg bisect to find when it broke in no time.
-
- OGRE Expert User
- Posts: 1148
- Joined: Sat Jul 06, 2013 10:59 pm
- Location: Chile
- x 169
Re: [2.1] Adding HLMS customisations per datablock
Something spooky is happening (might be because of Halloween?)
I checked again and its not entering this if (in fillBuffersForV2):
but it is entering this part (in calculateHashForPreCreate):
Then I remember that yesterday the scene was almost empty (when I was using the prev ogre version), now has some other objects, so I removed most of them and its working again! (so maybe its not about the ogre version)
Obviously that's not a solution, I need those objects, so I am guessing I am missing some hash stuffs regarding textures, I'll look in to that now
about the slots, that datablock is not using many textures so I don't think so, anyways I tried with other values and no luck (btw, the limit is 15? iirc)
thanks!!
I checked again and its not entering this if (in fillBuffersForV2):
Code: Select all
if( OGRE_EXTRACT_HLMS_TYPE_FROM_CACHE_HASH( lastCacheHash ) != mType )
{
if( !datablock->getDisplaceTexture().isNull() ){
Code: Select all
if( !datablock->getDisplaceTexture().isNull() ){
setProperty( "displace_map", 1 );
}
Obviously that's not a solution, I need those objects, so I am guessing I am missing some hash stuffs regarding textures, I'll look in to that now
about the slots, that datablock is not using many textures so I don't think so, anyways I tried with other values and no luck (btw, the limit is 15? iirc)
thanks!!
-
- OGRE Expert User
- Posts: 1148
- Joined: Sat Jul 06, 2013 10:59 pm
- Location: Chile
- x 169
Re: [2.1] Adding HLMS customisations per datablock
I implemented calculateHash(), copy pasted everything and added this:
also tried adding this:
no luck =(
Code: Select all
if( !mDisplaceTexture.isNull() ){
hash += Ogre::IdString( mDisplaceTexture->getName() );
}
Code: Select all
void yHlmsPbsDatablockExtended::setDisplaceTexture( Ogre::TexturePtr texture ){
mDisplaceTexture = texture;
calculateHash(); //<<<<<<<<<<<<<
flushRenderables(); //<<<<<<<<<<<<<
}
-
- OGRE Team Member
- Posts: 5436
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1343
Re: [2.1] Adding HLMS customisations per datablock
Oh!
Now I see the problem.
When you do:
This is only executed ideally once (in practice multiple times, depending on whether there are materials using other types of Hlms interleaved with objects using HlmsPbs).
So in other words whatever happens inside is meant for commands that have global impact. Like for example a shadow map or forward+ (which is used by all objects/materials and may occasionally be ignored by an object, but even if ignored the generated shader is prepared to assume the slots are taken, etc)
However when you do:
This is not global: it is grabbing the datablock from the Renderable being processed. So if the first Renderable being rendered (or the first Renderable after switching back from a different Hlms type) does not have a displacement texture, it won't work. Whether this works is dependent on objects and their distance to camera (among other things).
If the displacement texture is just one for everybody, then fix this issue (by holding the displacement texture in yHlmsPbsExtended instead of using the pointer from datablock->getDisplaceTexture). Even if it's global, keep your change to calculateHash though, it could help Ogre with render queue sorting to have faster rendering.
If there can be multiple/different displacement textures, then you'll have to drop the "if( OGRE_EXTRACT_HLMS_TYPE_FROM_CACHE_HASH( lastCacheHash ) != mType )", because that's wrong and use this:
Btw if you somehow manage to sneak the displacement texture into mBakedTextures you may even not have to do this (but now the texture unit count will not be fixed at 13). Sounds complicated though. Forget I said anything
Now I see the problem.
When you do:
Code: Select all
if( OGRE_EXTRACT_HLMS_TYPE_FROM_CACHE_HASH( lastCacheHash ) != mType )
{
So in other words whatever happens inside is meant for commands that have global impact. Like for example a shadow map or forward+ (which is used by all objects/materials and may occasionally be ignored by an object, but even if ignored the generated shader is prepared to assume the slots are taken, etc)
However when you do:
Code: Select all
if( OGRE_EXTRACT_HLMS_TYPE_FROM_CACHE_HASH( lastCacheHash ) != mType )
{
if( !datablock->getDisplaceTexture().isNull() ){
If the displacement texture is just one for everybody, then fix this issue (by holding the displacement texture in yHlmsPbsExtended instead of using the pointer from datablock->getDisplaceTexture). Even if it's global, keep your change to calculateHash though, it could help Ogre with render queue sorting to have faster rendering.
If there can be multiple/different displacement textures, then you'll have to drop the "if( OGRE_EXTRACT_HLMS_TYPE_FROM_CACHE_HASH( lastCacheHash ) != mType )", because that's wrong and use this:
Code: Select all
uint32 lastTextureHash = mLastTextureHash; //Save the value because it will be modified in HlmsPbs::fillBuffersForV2
...
Ogre::uint32 retVal = HlmsPbs::fillBuffersForV2( cache, queuedRenderable, casterPass, lastCacheHash, commandBuffer );
...
if( datablock->mTextureHash != lastTextureHash && !datablock->getDisplaceTexture().isNull() )
{
...
}
-
- OGRE Expert User
- Posts: 1148
- Joined: Sat Jul 06, 2013 10:59 pm
- Location: Chile
- x 169
Re: [2.1] Adding HLMS customisations per datablock
I love you, its working now
-
- Gnoblar
- Posts: 7
- Joined: Tue Aug 24, 2021 7:52 am
Re: [2.1] Adding HLMS customisations per datablock
dark_sylinc wrote: ↑Wed Jan 27, 2016 10:22 pm As for making the changes per Datablock:
At shader level: I realize there is no custom_ps_ piece for adding more data. This can be easily be fixed.
At C++ level: I don't think a listener is a good idea. It wouldn't be clean and would be complicated. The best method I see is deriving from both HlmsPbs and HlmsPbsDatablock:A small modification to Ogre would be required so that ConstBufferPool() gets the HlmsMyDatablock::MaterialSizeInGpuAligned instead of HlmsPbsDatablock::MaterialSizeInGpuAligned.Code: Select all
class HlmsMyDatablock : public HlmsPbsDatablock { //Override what we send to the GPU (usually to send [i]more[/i] data) virtual void uploadToConstBuffer( char *dstPtr ); } class HlmsMy : public HlmsPbs { //Override to return a HlmsMyDatablock. virtual HlmsDatablock* createDatablockImpl( IdString datablockName, const HlmsMacroblock *macroblock, const HlmsBlendblock *blendblock, const HlmsParamVec ¶mVec ); }
And then you're set.
As for making the changes per Renderable:
Again, no listener, this time the reason is performance. But this time it involves overloading HlmsPbs::fillBuffersFor so we can send more information via mCurrentMappedConstBuffer or mCurrentMappedTexBuffer.
This method is the biggest of all (in terms of lines of code and work being done), so overloading it could involve a lot of copy pasting. It's definitely the most intrusive / less modular section; and the most difficult to maintain if the original codebase in the repo changes (however, it has been very stable by now).
Unfortunately mUserValues does not exists in HlmsUnlit, so I have to patch HlmsUnlit and HlmsUnlitDatablock to allow inherited classes to change const buffer size and append extra values with the help of two extra protected constructors, this is what I did:
Code: Select all
diff --color -Naur a/Components/Hlms/Unlit/include/OgreHlmsUnlit.h b/Components/Hlms/Unlit/include/OgreHlmsUnlit.h
--- a/Components/Hlms/Unlit/include/OgreHlmsUnlit.h 2021-09-13 11:32:05.044330000 +0800
+++ b/Components/Hlms/Unlit/include/OgreHlmsUnlit.h 2021-09-13 11:42:31.452233400 +0800
@@ -114,6 +114,9 @@
bool casterPass, uint32 lastCacheHash,
CommandBuffer *commandBuffer, bool isV1 );
+ HlmsUnlit( Archive *dataFolder, ArchiveVec *libraryFolders, size_t constBufferSize );
+ HlmsUnlit( Archive *dataFolder, ArchiveVec *libraryFolders,
+ HlmsTypes type, const String &typeName, size_t constBufferSize );
public:
HlmsUnlit( Archive *dataFolder, ArchiveVec *libraryFolders );
HlmsUnlit( Archive *dataFolder, ArchiveVec *libraryFolders,
diff --color -Naur a/Components/Hlms/Unlit/src/OgreHlmsUnlit.cpp b/Components/Hlms/Unlit/src/OgreHlmsUnlit.cpp
--- a/Components/Hlms/Unlit/src/OgreHlmsUnlit.cpp 2021-08-16 07:02:59.000000000 +0800
+++ b/Components/Hlms/Unlit/src/OgreHlmsUnlit.cpp 2021-09-13 11:36:29.991879400 +0800
@@ -71,10 +71,14 @@
{
extern const String c_unlitBlendModes[];
+
+ HlmsUnlit::HlmsUnlit( Archive *dataFolder, ArchiveVec *libraryFolders ) : HlmsUnlit(dataFolder, libraryFolders, HlmsUnlitDatablock::MaterialSizeInGpuAligned){}
+ HlmsUnlit::HlmsUnlit( Archive *dataFolder, ArchiveVec *libraryFolders,
+ HlmsTypes type, const String &typeName ) : HlmsUnlit(dataFolder, libraryFolders, type, typeName, HlmsUnlitDatablock::MaterialSizeInGpuAligned){}
- HlmsUnlit::HlmsUnlit( Archive *dataFolder, ArchiveVec *libraryFolders ) :
+ HlmsUnlit::HlmsUnlit( Archive *dataFolder, ArchiveVec *libraryFolders, size_t constBufferSize ) :
HlmsBufferManager( HLMS_UNLIT, "unlit", dataFolder, libraryFolders ),
- ConstBufferPool( HlmsUnlitDatablock::MaterialSizeInGpuAligned,
+ ConstBufferPool( constBufferSize,
ExtraBufferParams( 64 * NUM_UNLIT_TEXTURE_TYPES ) ),
mCurrentPassBuffer( 0 ),
mLastBoundPool( 0 ),
@@ -98,9 +102,9 @@
mPreparedPass.viewProjMatrix[4] = Matrix4::IDENTITY;
}
HlmsUnlit::HlmsUnlit( Archive *dataFolder, ArchiveVec *libraryFolders,
- HlmsTypes type, const String &typeName ) :
+ HlmsTypes type, const String &typeName, size_t constBufferSize ) :
HlmsBufferManager( type, typeName, dataFolder, libraryFolders ),
- ConstBufferPool( HlmsUnlitDatablock::MaterialSizeInGpuAligned,
+ ConstBufferPool( constBufferSize,
ExtraBufferParams( 64 * NUM_UNLIT_TEXTURE_TYPES ) ),
mCurrentPassBuffer( 0 ),
mLastBoundPool( 0 ),
Code: Select all
const size_t HlmsUnlitDatablockCustom::MaterialSizeInGpu = Ogre::HlmsUnlitDatablock::MaterialSizeInGpu + 4;
const size_t HlmsUnlitDatablockCustom::MaterialSizeInGpuAligned = Ogre::alignToNextMultiple(HlmsUnlitDatablockCustom::MaterialSizeInGpu, 4 * 4);
void HlmsUnlitDatablockCustom::uploadToConstBuffer( char *dstPtr, Ogre::uint8 dirtyFlags)
{
char* dstPtrOrig = dstPtr;
Ogre::HlmsUnlitDatablock::uploadToConstBuffer( dstPtr, dirtyFlags);
dstPtr = dstPtrOrig + Ogre::HlmsUnlitDatablock::MaterialSizeInGpu;
memcpy( dstPtr, &mCustomParameter, sizeof( mCustomParameter) );
}
...
HlmsUnlitCustom::HlmsUnlitCustom(Ogre::Archive* dataFolder, Ogre::ArchiveVec* libraryFolders) : Ogre::HlmsUnlit(dataFolder, libraryFolders, HlmsUnlitDatablockCustom::MaterialSizeInGpuAligned)
{
}