Best method to map constBuffer to objects?

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


Nucleartree
Kobold
Posts: 38
Joined: Tue Apr 04, 2017 9:10 pm
Location: Cardiff, UK
x 19

Best method to map constBuffer to objects?

Post by Nucleartree »

Hi everyone! I'm working on a system that shows and hides voxel terrain based on values in a const buffer. I have been able to get this working by using a const buffer of uint8 values to pass to the vertex shader. However I have noticed (at least on MacOS and Metal) that this breaks instancing, so things like my tree objects which use the same material and model are now drawn with an extra call to setVertexBuffer and then the draw.

I got this working by creating the const buffer like this:

Code: Select all

        Ogre::RenderSystem *renderSystem = Ogre::Root::getSingletonPtr()->getRenderSystem();
        Ogre::VaoManager *vaoManager = renderSystem->getVaoManager();
        AV::uint8* regionAnimationBuffer = new AV::uint8[600 * 600];
        for(int i = 0; i < 600 * 600; i++){
            *(regionAnimationBuffer + i) = 0x80;
        }
        Ogre::ConstBufferPacked *hlmsBuffer = vaoManager->createConstBuffer( sizeof(AV::uint8) * 600 * 600, Ogre::BT_DEFAULT, 0, false );
        hlmsBuffer->upload( regionAnimationBuffer, 0u, sizeof(AV::uint8) * 600 * 600 );

Then I overrode the fillBuffersForV2 function by creating a superclass for hlmsPBS

Code: Select all

    Ogre::uint32 HlmsPbsAVCustom::fillBuffersForV2(const Ogre::HlmsCache *cache, const Ogre::QueuedRenderable &queuedRenderable, bool casterPass, Ogre::uint32 lastCacheHash, Ogre::CommandBuffer *commandBuffer){
        Ogre::uint32 result =
        HlmsPbs::fillBuffersForV2(cache, queuedRenderable, casterPass, lastCacheHash, commandBuffer);

    for(HlmsAVCustomListener* listener : mAVCustomListeners){
        listener->fillBuffersForV2(cache, queuedRenderable, casterPass, lastCacheHash, commandBuffer);
    }

    return result;
}

I call registered listener objects here for flexibility

Here is the listener

Code: Select all

        Ogre::uint32 fillBuffersForV2(const Ogre::HlmsCache *cache, const Ogre::QueuedRenderable &queuedRenderable, bool casterPass, Ogre::uint32 lastCacheHash, Ogre::CommandBuffer *commandBuffer){
            *commandBuffer->addCommand<Ogre::CbShaderBuffer>() = Ogre::CbShaderBuffer(Ogre::VertexShader, Ogre::uint16( 3 ), mHlmsBuffer, 0, (Ogre::uint32)mHlmsBuffer->getTotalSizeBytes() );

        return 0;
    }

This works and the buffer is mapped ok, but the lack of instancing is a problem. From looking at the code the constBufferSlot variable isn't actually used. I really would prefer not to have to modify hlmsPBS so hoping I can just stick with something along these lines. I'm just wondering if there is a better way to do this though? Thanks!

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5534
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1394

Re: Best method to map constBuffer to objects?

Post by dark_sylinc »

The problem is that every time you call commandBuffer->addCommand<>() you're going to break instancing.
You must avoid making such call if it's not necessary, by tracking whether you've called it already and if it's necessary.

Btw your const buffer is 360kb which is definitely above the limit for NVIDIA (NV has a limit of 64kb). ReadOnlyBuffers are better suited if you need more than 64kb (or you can use multiple const buffers).