Program Listing for File data-manager.h

Return to documentation for file (include\data-manager\data-manager.h)

/******************************************************************************
© Intel Corporation.

This software and the related documents are Intel copyrighted materials,
and your use of them is governed by the express license under which they
were provided to you ("License"). Unless the License provides otherwise,
you may not use, modify, copy, publish, distribute, disclose or transmit
this software or the related documents without Intel's prior written
permission.


 This software and the related documents are provided as is, with no express
or implied warranties, other than those that are expressly stated in the
License.

******************************************************************************/

#pragma once

#include "concurrent/lock.h"

#include "utility/data-desc.h"
#include "utility/coverage-map.h"

#include <memory>
#include <unordered_map>
#include <vector>
#include <string>

struct ID3D11ClassLinkage;
struct D3D11_INPUT_ELEMENT_DESC;

namespace gpa {

struct ResourceDataDescriptor;

namespace capture_support {

struct IObjectDataSource;

struct IVisitable
{
    virtual ~IVisitable();
    virtual void PreVisit(){};
    virtual void PostVisit() = 0;
};

class ObjectData : public IVisitable
{
public:
    typedef std::shared_ptr<ObjectData> Ptr;

    ObjectData();
    ~ObjectData();

    // IVisitable implementation
    void PostVisit() override;

    // used for basic RTTI
    virtual bool IsMappedObjectData() const;

    // "Zombie" objects are required to support the Intel Arc D3D12 driver's implementation of
    // 64-bit emulated atomics extension in Unreal 5.1+ workloads (this is required for Nanite
    // to work). The nature of the extension implementation in the driver is such that, for
    // deferred and subcapture, we need to restore some objects (devices and extension-specific
    // resources) that were otherwise destroyed, prior to restore point state capture, during
    // execution of the workload. When the specified objects are destroyed during application
    // runtime, we mark them as "zombies" to keep them around for later enumeration during
    // state capture creation.
    virtual bool IsZombie() const;
    virtual void MakeZombie();

    void AddDependency(Ptr objectData);

protected:
    // list of other ObjectData on which I may depend
    std::vector<Ptr> mDependencies;

    // if this is a "zombie" object -- it's been deleted elsewhere, but
    // for some reason, the call cache should remain (for keyframe/deferred
    // purposes, for example)
    bool mZombie;
};

struct IObjectDataSource
{
    virtual ~IObjectDataSource();
    virtual ObjectData::Ptr GetDataForKey(void const* key) const = 0;
};

class MappedObjectData : public ObjectData
{
public:
    typedef std::shared_ptr<MappedObjectData> Ptr;

    MappedObjectData();
    ~MappedObjectData();

    // ObjectData implementation
    bool IsMappedObjectData() const override;

    virtual void Apply(ResourceDataDescriptor const* desc);

    virtual void SaveChunkForRestore(ResourceDataDescriptor const* desc);

    virtual bool HasChunksToRestore() const;

    virtual void RestoreChunks(void* baseMappedObjectAddress);

protected:
    virtual void* GetBufferPtr() = 0;

    struct ModifiedChunk
    {
        ResourceDataDescriptor resourceDescriptor;
        std::vector<uint8_t> originalData;
    };

    std::vector<ModifiedChunk> mModifiedChunks;
    utility::CoverageMap mCoverageMap;
};

struct ObjectVisitor
{
    virtual ~ObjectVisitor();
    virtual bool Visit(ObjectData* object) = 0;
};

class DataManager
{
public:
    // TODO: KeyframeWriter depends on the type of ObjectRef; until we move this
    //       to a common location, make sure that stays in sync with changes to
    //       this declaration
    typedef uint64_t ObjectRef;
    typedef void* Key;

    DataManager();

    // @details Release() will be called on all contained entries.
    ~DataManager();

    ObjectData::Ptr GetAssociatedDataRef(ObjectRef object, Key key);

    void AssociateDataRefForObject(ObjectRef object, Key key, ObjectData::Ptr data, bool retain = false, ObjectRef* retainedObjectId = nullptr);

    typedef void (*ObjectEnumerationCallback)(ObjectRef object, Key key, ObjectData::Ptr data, void* userData);
    void EnumerateObjectsWithKey(ObjectEnumerationCallback callback, Key key, void* userData);
    void EnumerateObjectsWithKeys(ObjectEnumerationCallback callback, Key const* keys, size_t nKeys, void* userData);

    void VisitAll(ObjectVisitor* visitor, void* key) const;

    struct KeyedObjectData
    {
        Key key;
        ObjectData::Ptr data;
    };

    void Clear();

private:
    RWLock mRWLock;

    typedef std::vector<KeyedObjectData> KeyedData;
    typedef std::unordered_map<ObjectRef, KeyedData> ObjectKeyMap;
    ObjectKeyMap mObjectData;
};

}  // namespace capture_support

namespace playback {

struct ObjectReplacementKeyData : capture_support::ObjectData
{
    typedef std::shared_ptr<ObjectReplacementKeyData> Ptr;
    uint64_t replacementKey;
};

struct ID3D11ShaderCreateInfo : public capture_support::ObjectData
{
    typedef std::shared_ptr<ID3D11ShaderCreateInfo> Ptr;
    const void* pShaderBytecode;
    size_t bytecodeLength;
    ID3D11ClassLinkage* classLinkage;
};

struct ID3D11InputLayoutCreateInfo : public capture_support::ObjectData
{
    typedef std::shared_ptr<ID3D11InputLayoutCreateInfo> Ptr;
    std::vector<D3D11_INPUT_ELEMENT_DESC> InputElementDescs;
    std::vector<std::string> InputElementDescsSemanticNames;
};

}  //namespace playback

}  // namespace gpa