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