Home | History | Annotate | Download | only in client
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // This file contains the definition of the FencedAllocator class.
      6 
      7 #ifndef GPU_COMMAND_BUFFER_CLIENT_FENCED_ALLOCATOR_H_
      8 #define GPU_COMMAND_BUFFER_CLIENT_FENCED_ALLOCATOR_H_
      9 
     10 #include <vector>
     11 
     12 #include "base/logging.h"
     13 #include "gpu/command_buffer/common/types.h"
     14 #include "gpu/gpu_export.h"
     15 
     16 namespace gpu {
     17 class CommandBufferHelper;
     18 
     19 // FencedAllocator provides a mechanism to manage allocations within a fixed
     20 // block of memory (storing the book-keeping externally). Furthermore this
     21 // class allows to free data "pending" the passage of a command buffer token,
     22 // that is, the memory won't be reused until the command buffer has processed
     23 // that token.
     24 //
     25 // NOTE: Although this class is intended to be used in the command buffer
     26 // environment which is multi-process, this class isn't "thread safe", because
     27 // it isn't meant to be shared across modules. It is thread-compatible though
     28 // (see http://www.corp.google.com/eng/doc/cpp_primer.html#thread_safety).
     29 class GPU_EXPORT FencedAllocator {
     30  public:
     31   typedef unsigned int Offset;
     32   // Invalid offset, returned by Alloc in case of failure.
     33   static const Offset kInvalidOffset = 0xffffffffU;
     34 
     35   // Creates a FencedAllocator. Note that the size of the buffer is passed, but
     36   // not its base address: everything is handled as offsets into the buffer.
     37   FencedAllocator(unsigned int size,
     38                   CommandBufferHelper *helper);
     39 
     40   ~FencedAllocator();
     41 
     42   // Allocates a block of memory. If the buffer is out of directly available
     43   // memory, this function may wait until memory that was freed "pending a
     44   // token" can be re-used.
     45   //
     46   // Parameters:
     47   //   size: the size of the memory block to allocate.
     48   //
     49   // Returns:
     50   //   the offset of the allocated memory block, or kInvalidOffset if out of
     51   //   memory.
     52   Offset Alloc(unsigned int size);
     53 
     54   // Frees a block of memory.
     55   //
     56   // Parameters:
     57   //   offset: the offset of the memory block to free.
     58   void Free(Offset offset);
     59 
     60   // Frees a block of memory, pending the passage of a token. That memory won't
     61   // be re-allocated until the token has passed through the command stream.
     62   //
     63   // Parameters:
     64   //   offset: the offset of the memory block to free.
     65   //   token: the token value to wait for before re-using the memory.
     66   void FreePendingToken(Offset offset, int32 token);
     67 
     68   // Frees any blocks pending a token for which the token has been read.
     69   void FreeUnused();
     70 
     71   // Gets the size of the largest free block that is available without waiting.
     72   unsigned int GetLargestFreeSize();
     73 
     74   // Gets the size of the largest free block that can be allocated if the
     75   // caller can wait. Allocating a block of this size will succeed, but may
     76   // block.
     77   unsigned int GetLargestFreeOrPendingSize();
     78 
     79   // Checks for consistency inside the book-keeping structures. Used for
     80   // testing.
     81   bool CheckConsistency();
     82 
     83   // True if any memory is allocated.
     84   bool InUse();
     85 
     86   // Return bytes of memory that is IN_USE
     87   size_t bytes_in_use() const { return bytes_in_use_; }
     88 
     89  private:
     90   // Status of a block of memory, for book-keeping.
     91   enum State {
     92     IN_USE,
     93     FREE,
     94     FREE_PENDING_TOKEN
     95   };
     96 
     97   // Book-keeping sturcture that describes a block of memory.
     98   struct Block {
     99     State state;
    100     Offset offset;
    101     unsigned int size;
    102     int32 token;  // token to wait for in the FREE_PENDING_TOKEN case.
    103   };
    104 
    105   // Comparison functor for memory block sorting.
    106   class OffsetCmp {
    107    public:
    108     bool operator() (const Block &left, const Block &right) {
    109       return left.offset < right.offset;
    110     }
    111   };
    112 
    113   typedef std::vector<Block> Container;
    114   typedef unsigned int BlockIndex;
    115 
    116   static const int32 kUnusedToken = 0;
    117 
    118   // Gets the index of a memory block, given its offset.
    119   BlockIndex GetBlockByOffset(Offset offset);
    120 
    121   // Collapse a free block with its neighbours if they are free. Returns the
    122   // index of the collapsed block.
    123   // NOTE: this will invalidate block indices.
    124   BlockIndex CollapseFreeBlock(BlockIndex index);
    125 
    126   // Waits for a FREE_PENDING_TOKEN block to be usable, and free it. Returns
    127   // the new index of that block (since it may have been collapsed).
    128   // NOTE: this will invalidate block indices.
    129   BlockIndex WaitForTokenAndFreeBlock(BlockIndex index);
    130 
    131   // Allocates a block of memory inside a given block, splitting it in two
    132   // (unless that block is of the exact requested size).
    133   // NOTE: this will invalidate block indices.
    134   // Returns the offset of the allocated block (NOTE: this is different from
    135   // the other functions that return a block index).
    136   Offset AllocInBlock(BlockIndex index, unsigned int size);
    137 
    138   CommandBufferHelper *helper_;
    139   Container blocks_;
    140   size_t bytes_in_use_;
    141 
    142   DISALLOW_IMPLICIT_CONSTRUCTORS(FencedAllocator);
    143 };
    144 
    145 // This class functions just like FencedAllocator, but its API uses pointers
    146 // instead of offsets.
    147 class FencedAllocatorWrapper {
    148  public:
    149   FencedAllocatorWrapper(unsigned int size,
    150                          CommandBufferHelper* helper,
    151                          void* base)
    152       : allocator_(size, helper),
    153         base_(base) { }
    154 
    155   // Allocates a block of memory. If the buffer is out of directly available
    156   // memory, this function may wait until memory that was freed "pending a
    157   // token" can be re-used.
    158   //
    159   // Parameters:
    160   //   size: the size of the memory block to allocate.
    161   //
    162   // Returns:
    163   //   the pointer to the allocated memory block, or NULL if out of
    164   //   memory.
    165   void *Alloc(unsigned int size) {
    166     FencedAllocator::Offset offset = allocator_.Alloc(size);
    167     return GetPointer(offset);
    168   }
    169 
    170   // Allocates a block of memory. If the buffer is out of directly available
    171   // memory, this function may wait until memory that was freed "pending a
    172   // token" can be re-used.
    173   // This is a type-safe version of Alloc, returning a typed pointer.
    174   //
    175   // Parameters:
    176   //   count: the number of elements to allocate.
    177   //
    178   // Returns:
    179   //   the pointer to the allocated memory block, or NULL if out of
    180   //   memory.
    181   template <typename T> T *AllocTyped(unsigned int count) {
    182     return static_cast<T *>(Alloc(count * sizeof(T)));
    183   }
    184 
    185   // Frees a block of memory.
    186   //
    187   // Parameters:
    188   //   pointer: the pointer to the memory block to free.
    189   void Free(void *pointer) {
    190     DCHECK(pointer);
    191     allocator_.Free(GetOffset(pointer));
    192   }
    193 
    194   // Frees a block of memory, pending the passage of a token. That memory won't
    195   // be re-allocated until the token has passed through the command stream.
    196   //
    197   // Parameters:
    198   //   pointer: the pointer to the memory block to free.
    199   //   token: the token value to wait for before re-using the memory.
    200   void FreePendingToken(void *pointer, int32 token) {
    201     DCHECK(pointer);
    202     allocator_.FreePendingToken(GetOffset(pointer), token);
    203   }
    204 
    205   // Frees any blocks pending a token for which the token has been read.
    206   void FreeUnused() {
    207     allocator_.FreeUnused();
    208   }
    209 
    210   // Gets a pointer to a memory block given the base memory and the offset.
    211   // It translates FencedAllocator::kInvalidOffset to NULL.
    212   void *GetPointer(FencedAllocator::Offset offset) {
    213     return (offset == FencedAllocator::kInvalidOffset) ?
    214         NULL : static_cast<char *>(base_) + offset;
    215   }
    216 
    217   // Gets the offset to a memory block given the base memory and the address.
    218   // It translates NULL to FencedAllocator::kInvalidOffset.
    219   FencedAllocator::Offset GetOffset(void *pointer) {
    220     return pointer ?
    221         static_cast<FencedAllocator::Offset>(
    222             static_cast<char*>(pointer) - static_cast<char*>(base_)) :
    223         FencedAllocator::kInvalidOffset;
    224   }
    225 
    226   // Gets the size of the largest free block that is available without waiting.
    227   unsigned int GetLargestFreeSize() {
    228     return allocator_.GetLargestFreeSize();
    229   }
    230 
    231   // Gets the size of the largest free block that can be allocated if the
    232   // caller can wait.
    233   unsigned int GetLargestFreeOrPendingSize() {
    234     return allocator_.GetLargestFreeOrPendingSize();
    235   }
    236 
    237   // Checks for consistency inside the book-keeping structures. Used for
    238   // testing.
    239   bool CheckConsistency() {
    240     return allocator_.CheckConsistency();
    241   }
    242 
    243   // True if any memory is allocated.
    244   bool InUse() {
    245     return allocator_.InUse();
    246   }
    247 
    248   FencedAllocator &allocator() { return allocator_; }
    249 
    250   size_t bytes_in_use() const { return allocator_.bytes_in_use(); }
    251 
    252  private:
    253   FencedAllocator allocator_;
    254   void* base_;
    255   DISALLOW_IMPLICIT_CONSTRUCTORS(FencedAllocatorWrapper);
    256 };
    257 
    258 }  // namespace gpu
    259 
    260 #endif  // GPU_COMMAND_BUFFER_CLIENT_FENCED_ALLOCATOR_H_
    261