Jump to content

Recommended Posts

Posted

 

while developing the PBR Texture generator I have found some flaw with the current hook system. It is somewhat inflexible. Soi tried to add my own Hook Manager:

enum class HookState
{
    IDLE,
    PENDING,
    RUNNING,
    FINISHED,
};
class HookManager;

class Hook : public Object
{
    friend class HookManager;

private:
    void* _function;
    shared_ptr<Object> _extra;
    HookState _currentState;
    bool _stopping = false;
    bool _repeating = false;
    shared_ptr<HookManager> _manager;
public:
    
    Hook(shared_ptr<HookManager> manager, void callback(const UltraEngine::Render::VkRenderer&, shared_ptr<Object>), shared_ptr<Object> extra, bool repeat = false)
    {
        _function = callback;
        _extra = extra;
        _currentState = HookState::IDLE;
        _repeating = repeat;
        _manager = manager;
    }

    void Start()
    {
        _currentState = HookState::PENDING;
    }

    void Stop()
    {
        _stopping = true;
    }

    HookState GetState() { return _currentState; }

    void SetExtra(shared_ptr<Object> extra)
    {
        _extra = extra;
    }
};

class HookManager : public Object
{
    friend class Hook;

private:
    static void UpdateDispatch(const UltraEngine::Render::VkRenderer& renderer, shared_ptr<Object> extra)
    {
        auto hookManager = extra->As<HookManager>();
        if (hookManager != NULL)
        {
            for (auto hook : hookManager->_hooks)
            {
                if (hook->_stopping)
                {
                    hook->_currentState = HookState::IDLE;
                    hook->_stopping = false;
                }

                if (hook->GetState() != HookState::FINISHED)
                {
                    if (hook->GetState() == HookState::PENDING)
                    {
                        hook->_currentState = HookState::RUNNING;
                        auto f = (void(*)(const UltraEngine::Render::VkRenderer&, shared_ptr<Object>))hook->_function;
                        f(renderer, hook->_extra);
                    }
                    else if (hook->GetState() == HookState::RUNNING)
                    {
                        if (!hook->_repeating)
                        {
                            hook->_currentState = HookState::FINISHED;
                        }
                        else
                        {
                            hook->_currentState = HookState::PENDING;
                        }
                    }
                }
            }
        }
    }

    inline static map<HookID,map<shared_ptr<World>, shared_ptr<HookManager>>> _mapWorldHookManager;

    vector<shared_ptr<Hook>> _hooks;
    shared_ptr<World> _world;
    HookID _hookId;

public:
    static shared_ptr<HookManager> Get(shared_ptr<World> world, HookID hookId)
    {
        if (_mapWorldHookManager.size() == 0)
        {
            _mapWorldHookManager[HOOKID_RENDER] = {};
            _mapWorldHookManager[HOOKID_TRANSFER] = {};
        }

        if (HookManager::_mapWorldHookManager[hookId][world] == NULL)
        {
            auto mgr = std::make_shared<HookManager>(world, hookId);
            mgr->StartDispatching();
            HookManager::_mapWorldHookManager[hookId][world] = mgr;
        }

        return HookManager::_mapWorldHookManager[hookId][world];
    }

    void StartDispatching()
    {
        _world->AddHook(HookID::HOOKID_TRANSFER, HookManager::UpdateDispatch, Self(), true);
    }

    void Start(shared_ptr<Hook> hook)
    {
        auto position = std::find(_hooks.begin(), _hooks.end(), hook);
        if (position != _hooks.end())
        {
            hook->Start();
        }
    }

    void Stop(shared_ptr<Hook> hook)
    {
        auto position = std::find(_hooks.begin(), _hooks.end(), hook);
        if (position != _hooks.end())
        {
            hook->Stop();
        }
    }

    HookManager(shared_ptr<World> world, HookID hookId)
    {
        _world = world;
        _hookId = hookId;
    }

    shared_ptr<Hook> AddHook(void callback(const UltraEngine::Render::VkRenderer&, shared_ptr<Object>), shared_ptr<Object> extra , bool repeat = false)
    {
        auto hook = std::make_shared<Hook>(Self()->As<HookManager>(), callback, extra, repeat);
        _hooks.push_back(hook);
        return hook;
    }

    void RemoveHook(shared_ptr<Hook> hook)
    {
        auto position = std::find(_hooks.begin(), _hooks.end(), hook);
        if (position != _hooks.end())
            _hooks.erase(position);
    }
};

 It allows to dispatch, Start/Stop hooks like a thread and also adds the ability check the state of a hook. 

static void checkCallback(const UltraEngine::Render::VkRenderer&, shared_ptr<Object>)
{
}
  
auto hookManager = HookManager::Get(_world, HOOKID_TRANSFER);
auto checkHook = _hookManager->AddHook(checkCallback, _world, false);
hookManager->Start(checkHook);
  
while(checkHook->GetState() != HookState::Finished)
{
  world->Update();
  world->Render();
}  
 
  

This makes it a bit easier to watch the Hook execution.

I use it in my PBRTextureGen and in my current state of Computeshader Implementation. It makes it much easier to manage the hooks. It might stll have a few bugs in it as i haven't fully tested every usecase, but for the basics it works :)

 

 

  • Windows 10 Pro 64-Bit-Version
  • NVIDIA Geforce 1080 TI

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...