Poor performance custom function for VEX using HDK!

   1071   1   2
User Avatar
Member
209 posts
Joined: March 2018
Offline
Hey folks!
I got some troubles while creating a custom VEX function via HDK.
I need to access geometry data inside the function at different frame on specific node inside my custom C++ function which should be used by VEX and I used two methods for doing this:
  1. Using GU_SopQuery class to access geometry data on the given node address in for example "op:/obj/geo1/OUT_Volume" format.
    Here is the sample:
    #include <iostream>
    #include <VEX/VEX_VexOp.h>
    #include <OP/OP_Director.h>
    #include <GU/GU_Detail.h>
    #include <SOP/SOP_Node.h>
    #include <GEO/GEO_VolumeSampler.h>
    #include <GU/GU_PrimVolume.h>
    #include <GU/GU_SopResolver.h>
    
    template <VEX_Precision PREC>
    static void
    wetmap(int argc, void *argv[], void *)
    {
        const char *surfaceAddress = static_cast<const char *>(argv[0]);
        const VEXvec3<PREC> *P = static_cast<const VEXvec3<PREC>*>(argv[1]);
        const VEXvec3<PREC> *Cd = static_cast<const VEXvec3<PREC>*>(argv[2]);
        VEXvec3<PREC> *resultCd = static_cast<VEXvec3<PREC>*>(argv[3]);
        *resultCd = *Cd;
    
        exint currentFrame = CHgetFrameFromTime(CHgetEvalTime());
        GU_SopQuery quary;
    
        for (exint frame = currentFrame; frame > 0; --frame)
        {
            quary.setFrame(frame);
            GU_ConstDetailHandle handle = quary.getDetail(surfaceAddress);
            if (handle.isValid())
            {
                const GU_Detail *gdp = handle.gdp();
                const GEO_PrimVolume* volume = static_cast<const GEO_PrimVolume *>(gdp->getGEOPrimitive(0));
                if (volume != nullptr)
                {
                    GEO_VolumeSampler volumeSampler{volume};
                    *resultCd = volumeSampler.getValueF(*P);
                }
            }
        }
    }
    void
    newVEXOp(void *)
    {
        using UT::Literal::operator""_sh;
        new VEX_VexOp("wetness@SVV&V"_sh,      // Signature
                      wetmap<VEX_32>,         // Evaluator 32
                      wetmap<VEX_64>         // Evaluator 64
                      );
    }
    
  2. Creating a OP_Context instance at specific frame and pass it to SOP_Node::getCookedGeoHandle function to access to geometry data.
    Here is the sample:
    #include <iostream>
    #include <VEX/VEX_VexOp.h>
    #include <OP/OP_Director.h>
    #include <GU/GU_Detail.h>
    #include <SOP/SOP_Node.h>
    #include <GEO/GEO_VolumeSampler.h>
    #include <GU/GU_PrimVolume.h>
    #include <GU/GU_SopResolver.h>
    template <VEX_Precision PREC>
    static void
    wetmap(int argc, void *argv[], void *)
    {
        const char * surfaceAddress = static_cast<const char *>(argv[0]);
        VEXvec3<PREC> *P = static_cast<VEXvec3<PREC>*>(argv[1]);
        VEXvec3<PREC> *Cd = static_cast<VEXvec3<PREC>*>(argv[2]);
        VEXvec3<PREC> *resultCd = static_cast<VEXvec3<PREC>*>(argv[3]);
        *resultCd = *Cd;
    
        SOP_Node *sufaceNode = OPgetDirector()->findSOPNode(surfaceAddress);
    
        OP_Context context{OP_Context::CurrentEvalTime};
        exint currentFrame = context.getFrame();
    
        if(sufaceNode != nullptr)
        {
            GEO_VolumeSampler volume;
            GU_DetailHandle gd_handle = sufaceNode->getCookedGeoHandle(context);
            if(!gd_handle.isNull())
            {
                const GU_Detail* gdp = gd_handle.gdp();
                const GEO_PrimVolume* volume = static_cast<const GEO_PrimVolume *>(gdp->getGEOPrimitive(0));
                GEO_VolumeSampler volumeSampler{volume};
                if (volume != nullptr)
                {
                    for (exint i = currentFrame; i > 0; --i)
                    {
    
                        fpreal sample = volumeSampler.getValueF(*P);
                        *resultCd = sample;
                    }
                }
            }
        }
    }
    void
    newVEXOp(void *)
    {
        using UT::Literal::operator""_sh;
        new VEX_VexOp("wetness@SVV&V"_sh,      // Signature
                      wetmap<VEX_32>,         // Evaluator 32
                      wetmap<VEX_64>         // Evaluator 64
                      );
    }
    
The first method is completely slower than the second method but both methods are still slow to process in Point Wrangle!
The FPS for the first method on my machine while playing is around 3 and for the second method is around 10.
Since we can't access geometry data in VEX directly I write similar code in VEX just for a rough comparison with HDK versions.
The FPS for pure VEX version is around 20!
Here is the VEX code:
for (int i = int(@Frame); i > 0; --i)
{
    v@Cd = volumesample(chs("address"), 0, v@P);
}
Can anyone explain why pure VEX version is really faster than two HDK methods above?
Thank you so much!
Edited by N-G - Jan. 28, 2021 05:29:22
User Avatar
Member
209 posts
Joined: March 2018
Offline
Anyone?
  • Quick Links