@@ -0,0 +1,225 @@
|
||||
//! Declarations for GPU memory management
|
||||
|
||||
#ifndef GPUHEAP_HPP_
|
||||
#define GPUHEAP_HPP_
|
||||
|
||||
#include "top.hpp"
|
||||
#include "thread/atomic.hpp"
|
||||
#include "device/gpu/gpudefs.hpp"
|
||||
|
||||
/*! \addtogroup GPU
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! GPU Device Implementation
|
||||
|
||||
namespace gpu {
|
||||
|
||||
class Device;
|
||||
class Heap;
|
||||
class Resource;
|
||||
class Memory;
|
||||
class VirtualGPU;
|
||||
|
||||
//! @todo:dgladdin: The heap list should be singly-linked
|
||||
|
||||
//! \brief A block on the GPU heap.
|
||||
//!
|
||||
//! Note that no code outside of the gpumemory.hpp/.cpp pair should touch this
|
||||
//! class directly as it is not thread-safe. In general, this class should be
|
||||
//! pretty much a struct and contain as little functionality as possible - just
|
||||
//! a constructor, destructor.
|
||||
//!
|
||||
//! Any other methods - in particular, anything that talks to CAL - should be no
|
||||
//! more than proxies for functionality implemented in Heap, as Heap is aware
|
||||
//! of the lock state.
|
||||
|
||||
class HeapBlock : public amd::HeapObject
|
||||
{
|
||||
public:
|
||||
//! Constructor
|
||||
HeapBlock(
|
||||
Heap* owner = NULL,
|
||||
size_t size = 0,
|
||||
size_t offset = 0,
|
||||
HeapBlock* next=NULL,
|
||||
HeapBlock* prev=NULL)
|
||||
: owner_(owner)
|
||||
, size_(size)
|
||||
, offset_(offset)
|
||||
, next_(next)
|
||||
, prev_(prev)
|
||||
, inUse_(false)
|
||||
, parent_(NULL)
|
||||
, memory_(NULL)
|
||||
{}
|
||||
|
||||
//! Destructor does some sanity checks.
|
||||
~HeapBlock();
|
||||
|
||||
//! Frees a heap block, returning its memory to the owning heap (proxy)
|
||||
void free();
|
||||
|
||||
//! Sets the GPU memory object associated with the heap block
|
||||
void setMemory(Memory* memory) { memory_ = memory; }
|
||||
|
||||
//! Gets the GPU memory object associated with the heap block
|
||||
Memory* getMemory() const { return memory_; }
|
||||
|
||||
//! Adds a heapblock view to the list of views
|
||||
void addView(HeapBlock* hb)
|
||||
{ views_.push_back(hb); hb->parent_ = this; }
|
||||
|
||||
//! Removes a heapblock view from the list of views
|
||||
void removeView(HeapBlock* hb) { views_.remove(hb); }
|
||||
|
||||
//! Destroys all views
|
||||
void destroyViewsMemory();
|
||||
|
||||
//! Creates all new views
|
||||
bool reallocateViews(
|
||||
HeapBlock* parent, //!< Parent heap block
|
||||
size_t shift //!< The new HeapBlock shift
|
||||
);
|
||||
|
||||
//! Gets the offset
|
||||
size_t offset() const { return offset_; }
|
||||
|
||||
Heap* owner_; //!< Heap that owns this block
|
||||
size_t size_; //!< Size of the block in bytes
|
||||
size_t offset_; //!< Offset of this block in the heap
|
||||
HeapBlock* next_; //!< Next block on the list, or NULL
|
||||
HeapBlock* prev_; //!< Previous block on the list, or NULL
|
||||
bool inUse_; //!< true if the block is in use
|
||||
HeapBlock* parent_; //!< The parent heap block for a view
|
||||
|
||||
private:
|
||||
//! Disable copy constructor
|
||||
HeapBlock(const HeapBlock&);
|
||||
|
||||
//! Disable assignment
|
||||
HeapBlock& operator=(const HeapBlock&);
|
||||
|
||||
Memory* memory_; //!< Memory object associated with the heap block
|
||||
std::list<HeapBlock*> views_; //!< The list of all allocated views
|
||||
};
|
||||
|
||||
class Heap : public amd::HeapObject
|
||||
{
|
||||
public:
|
||||
//! Minimal supported CAL granularity = 256 bytes / ElementSize
|
||||
static const size_t MinGranularity = 64;
|
||||
|
||||
//! The size of a heap element in bytes
|
||||
static const size_t ElementSize = 4;
|
||||
|
||||
//! The type of a heap element in bytes
|
||||
static const cmSurfFmt ElementType = CM_SURF_FMT_R32I;
|
||||
|
||||
Heap(
|
||||
Device& device //!< GPU device object
|
||||
);
|
||||
|
||||
virtual bool create(
|
||||
size_t totalSize, //!< total size of the allocated heap (bytes)
|
||||
bool remoteAlloc //!< allocate the heap in remote memory
|
||||
);
|
||||
|
||||
//! Heap destructor
|
||||
virtual ~Heap();
|
||||
|
||||
/*!
|
||||
* \brief Allocates memory from a heap (best-fit).
|
||||
* We round up to 4k granularity for alignment.
|
||||
*
|
||||
* \return A pointer to allocated heap block object.
|
||||
*/
|
||||
virtual HeapBlock* alloc(
|
||||
size_t size //! The allocation size
|
||||
);
|
||||
|
||||
//! Release memory back to a heap.
|
||||
virtual void free(HeapBlock* blk);
|
||||
|
||||
//! Copies this heap to another
|
||||
virtual bool copyTo(Heap* heap);
|
||||
|
||||
//! Gets the GPU resource associated with the global heap
|
||||
const Resource& resource() const { return *resource_; }
|
||||
|
||||
//! Read the page size (bytes)
|
||||
size_t granularityB() const;
|
||||
|
||||
//! Read the total free space (bytes)
|
||||
size_t freeSpace() const { return freeSize_; }
|
||||
|
||||
virtual bool isSane(void) const; //!< Checks heap sanity
|
||||
|
||||
//! Returns true if we have a virtual heap
|
||||
bool isVirtual() const { return virtualMode_; }
|
||||
|
||||
//! Returns the base virtual address of the heap
|
||||
uint64_t baseAddress() const { return baseAddress_; }
|
||||
|
||||
private:
|
||||
//! Insert a block into a list. Must be called under a lock.
|
||||
void insertBlock(HeapBlock** list, HeapBlock* node);
|
||||
|
||||
//! Merge a block into a list. Must be called under a lock.
|
||||
void mergeBlock(HeapBlock** list, HeapBlock* node);
|
||||
|
||||
//! Remove a block from a list. Must be called under a lock.
|
||||
void detachBlock(HeapBlock** list, HeapBlock* node);
|
||||
|
||||
//! Split a block into two pieces
|
||||
HeapBlock* splitBlock(HeapBlock* node, size_t size);
|
||||
|
||||
protected:
|
||||
Resource* resource_; //!< GPU resource referencing the heap memory
|
||||
HeapBlock* freeList_; //!< Head block for free list
|
||||
HeapBlock* busyList_; //!< Head block for busy list
|
||||
size_t freeSize_; //!< total free size of the heap
|
||||
Device& device_; //!< Device that owns this heap
|
||||
size_t granularity_; //!< Size of an allocation page
|
||||
amd::Monitor lock_; //!< Lock to serialise heap accesses
|
||||
bool virtualMode_; //!< Virtual mode
|
||||
uint64_t baseAddress_; //!< Virtual heap base address
|
||||
};
|
||||
|
||||
class VirtualHeap : public Heap
|
||||
{
|
||||
public:
|
||||
VirtualHeap(
|
||||
Device& device //!< GPU device object
|
||||
);
|
||||
|
||||
virtual bool create(
|
||||
size_t totalSize, //!< total size of the allocated heap (bytes)
|
||||
bool remoteAlloc //!< allocate the heap in remote memory
|
||||
);
|
||||
|
||||
//! Heap destructor
|
||||
virtual ~VirtualHeap();
|
||||
|
||||
/*!
|
||||
* \brief Allocates memory from a heap (best-fit).
|
||||
* We round up to 4k granularity for alignment.
|
||||
*
|
||||
* \return A pointer to allocated heap block object.
|
||||
*/
|
||||
virtual HeapBlock* alloc(
|
||||
size_t size //! The allocation size
|
||||
);
|
||||
|
||||
//! Release memory back to a heap.
|
||||
virtual void free(HeapBlock* blk);
|
||||
|
||||
//! Copies this heap to another
|
||||
virtual bool copyTo(Heap* heap);
|
||||
|
||||
virtual bool isSane(void) const; //!< Checks heap sanity
|
||||
};
|
||||
|
||||
} // namespace gpu
|
||||
|
||||
#endif // GPUHEAP_HPP_
|
||||
Reference in New Issue
Block a user