• 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 command buffer helper class.
6 
7 #ifndef GPU_COMMAND_BUFFER_CLIENT_CMD_BUFFER_HELPER_H_
8 #define GPU_COMMAND_BUFFER_CLIENT_CMD_BUFFER_HELPER_H_
9 
10 #include <string.h>
11 #include <time.h>
12 
13 #include "gpu/command_buffer/common/cmd_buffer_common.h"
14 #include "gpu/command_buffer/common/command_buffer.h"
15 #include "gpu/command_buffer/common/constants.h"
16 #include "gpu/gpu_export.h"
17 
18 namespace gpu {
19 
20 // Command buffer helper class. This class simplifies ring buffer management:
21 // it will allocate the buffer, give it to the buffer interface, and let the
22 // user add commands to it, while taking care of the synchronization (put and
23 // get). It also provides a way to ensure commands have been executed, through
24 // the token mechanism:
25 //
26 // helper.AddCommand(...);
27 // helper.AddCommand(...);
28 // int32 token = helper.InsertToken();
29 // helper.AddCommand(...);
30 // helper.AddCommand(...);
31 // [...]
32 //
33 // helper.WaitForToken(token);  // this doesn't return until the first two
34 //                              // commands have been executed.
35 class GPU_EXPORT CommandBufferHelper {
36  public:
37   explicit CommandBufferHelper(CommandBuffer* command_buffer);
38   virtual ~CommandBufferHelper();
39 
40   // Initializes the CommandBufferHelper.
41   // Parameters:
42   //   ring_buffer_size: The size of the ring buffer portion of the command
43   //       buffer.
44   bool Initialize(int32 ring_buffer_size);
45 
46   // Sets whether the command buffer should automatically flush periodically
47   // to try to increase performance. Defaults to true.
48   void SetAutomaticFlushes(bool enabled);
49 
50   // True if the context is lost.
51   bool IsContextLost();
52 
53   // Asynchronously flushes the commands, setting the put pointer to let the
54   // buffer interface know that new commands have been added. After a flush
55   // returns, the command buffer service is aware of all pending commands.
56   void Flush();
57 
58   // Flushes the commands, setting the put pointer to let the buffer interface
59   // know that new commands have been added. After a flush returns, the command
60   // buffer service is aware of all pending commands and it is guaranteed to
61   // have made some progress in processing them. Returns whether the flush was
62   // successful. The flush will fail if the command buffer service has
63   // disconnected.
64   bool FlushSync();
65 
66   // Waits until all the commands have been executed. Returns whether it
67   // was successful. The function will fail if the command buffer service has
68   // disconnected.
69   bool Finish();
70 
71   // Waits until a given number of available entries are available.
72   // Parameters:
73   //   count: number of entries needed. This value must be at most
74   //     the size of the buffer minus one.
75   void WaitForAvailableEntries(int32 count);
76 
77   // Inserts a new token into the command buffer. This token either has a value
78   // different from previously inserted tokens, or ensures that previously
79   // inserted tokens with that value have already passed through the command
80   // stream.
81   // Returns:
82   //   the value of the new token or -1 if the command buffer reader has
83   //   shutdown.
84   int32 InsertToken();
85 
86   // Waits until the token of a particular value has passed through the command
87   // stream (i.e. commands inserted before that token have been executed).
88   // NOTE: This will call Flush if it needs to block.
89   // Parameters:
90   //   the value of the token to wait for.
91   void WaitForToken(int32 token);
92 
93   // Called prior to each command being issued. Waits for a certain amount of
94   // space to be available. Returns address of space.
95   CommandBufferEntry* GetSpace(uint32 entries);
96 
97   // Typed version of GetSpace. Gets enough room for the given type and returns
98   // a reference to it.
99   template <typename T>
GetCmdSpace()100   T* GetCmdSpace() {
101     COMPILE_ASSERT(T::kArgFlags == cmd::kFixed, Cmd_kArgFlags_not_kFixed);
102     uint32 space_needed = ComputeNumEntries(sizeof(T));
103     void* data = GetSpace(space_needed);
104     return reinterpret_cast<T*>(data);
105   }
106 
107   // Typed version of GetSpace for immediate commands.
108   template <typename T>
GetImmediateCmdSpace(size_t data_space)109   T* GetImmediateCmdSpace(size_t data_space) {
110     COMPILE_ASSERT(T::kArgFlags == cmd::kAtLeastN, Cmd_kArgFlags_not_kAtLeastN);
111     uint32 space_needed = ComputeNumEntries(sizeof(T) + data_space);
112     void* data = GetSpace(space_needed);
113     return reinterpret_cast<T*>(data);
114   }
115 
116   // Typed version of GetSpace for immediate commands.
117   template <typename T>
GetImmediateCmdSpaceTotalSize(size_t total_space)118   T* GetImmediateCmdSpaceTotalSize(size_t total_space) {
119     COMPILE_ASSERT(T::kArgFlags == cmd::kAtLeastN, Cmd_kArgFlags_not_kAtLeastN);
120     uint32 space_needed = ComputeNumEntries(total_space);
121     void* data = GetSpace(space_needed);
122     return reinterpret_cast<T*>(data);
123   }
124 
last_token_read()125   int32 last_token_read() const {
126     return command_buffer_->GetLastToken();
127   }
128 
get_offset()129   int32 get_offset() const {
130     return command_buffer_->GetLastState().get_offset;
131   }
132 
133   // Common Commands
Noop(uint32 skip_count)134   void Noop(uint32 skip_count) {
135     cmd::Noop* cmd = GetImmediateCmdSpace<cmd::Noop>(
136         (skip_count - 1) * sizeof(CommandBufferEntry));
137     if (cmd) {
138       cmd->Init(skip_count);
139     }
140   }
141 
SetToken(uint32 token)142   void SetToken(uint32 token) {
143     cmd::SetToken* cmd = GetCmdSpace<cmd::SetToken>();
144     if (cmd) {
145       cmd->Init(token);
146     }
147   }
148 
SetBucketSize(uint32 bucket_id,uint32 size)149   void SetBucketSize(uint32 bucket_id, uint32 size) {
150     cmd::SetBucketSize* cmd = GetCmdSpace<cmd::SetBucketSize>();
151     if (cmd) {
152       cmd->Init(bucket_id, size);
153     }
154   }
155 
SetBucketData(uint32 bucket_id,uint32 offset,uint32 size,uint32 shared_memory_id,uint32 shared_memory_offset)156   void SetBucketData(uint32 bucket_id,
157                      uint32 offset,
158                      uint32 size,
159                      uint32 shared_memory_id,
160                      uint32 shared_memory_offset) {
161     cmd::SetBucketData* cmd = GetCmdSpace<cmd::SetBucketData>();
162     if (cmd) {
163       cmd->Init(bucket_id,
164                 offset,
165                 size,
166                 shared_memory_id,
167                 shared_memory_offset);
168     }
169   }
170 
SetBucketDataImmediate(uint32 bucket_id,uint32 offset,const void * data,uint32 size)171   void SetBucketDataImmediate(
172       uint32 bucket_id, uint32 offset, const void* data, uint32 size) {
173     cmd::SetBucketDataImmediate* cmd =
174         GetImmediateCmdSpace<cmd::SetBucketDataImmediate>(size);
175     if (cmd) {
176       cmd->Init(bucket_id, offset, size);
177       memcpy(ImmediateDataAddress(cmd), data, size);
178     }
179   }
180 
GetBucketStart(uint32 bucket_id,uint32 result_memory_id,uint32 result_memory_offset,uint32 data_memory_size,uint32 data_memory_id,uint32 data_memory_offset)181   void GetBucketStart(uint32 bucket_id,
182                       uint32 result_memory_id,
183                       uint32 result_memory_offset,
184                       uint32 data_memory_size,
185                       uint32 data_memory_id,
186                       uint32 data_memory_offset) {
187     cmd::GetBucketStart* cmd = GetCmdSpace<cmd::GetBucketStart>();
188     if (cmd) {
189       cmd->Init(bucket_id,
190                 result_memory_id,
191                 result_memory_offset,
192                 data_memory_size,
193                 data_memory_id,
194                 data_memory_offset);
195     }
196   }
197 
GetBucketData(uint32 bucket_id,uint32 offset,uint32 size,uint32 shared_memory_id,uint32 shared_memory_offset)198   void GetBucketData(uint32 bucket_id,
199                      uint32 offset,
200                      uint32 size,
201                      uint32 shared_memory_id,
202                      uint32 shared_memory_offset) {
203     cmd::GetBucketData* cmd = GetCmdSpace<cmd::GetBucketData>();
204     if (cmd) {
205       cmd->Init(bucket_id,
206                 offset,
207                 size,
208                 shared_memory_id,
209                 shared_memory_offset);
210     }
211   }
212 
command_buffer()213   CommandBuffer* command_buffer() const {
214     return command_buffer_;
215   }
216 
get_ring_buffer()217   Buffer get_ring_buffer() const {
218     return ring_buffer_;
219   }
220 
221   void FreeRingBuffer();
222 
HaveRingBuffer()223   bool HaveRingBuffer() const {
224     return ring_buffer_id_ != -1;
225   }
226 
usable()227   bool usable () const {
228     return usable_;
229   }
230 
ClearUsable()231   void ClearUsable() {
232     usable_ = false;
233   }
234 
235  private:
236   // Waits until get changes, updating the value of get_.
237   void WaitForGetChange();
238 
239   // Returns the number of available entries (they may not be contiguous).
AvailableEntries()240   int32 AvailableEntries() {
241     return (get_offset() - put_ - 1 + total_entry_count_) % total_entry_count_;
242   }
243 
244   bool AllocateRingBuffer();
245   void FreeResources();
246 
247   CommandBuffer* command_buffer_;
248   int32 ring_buffer_id_;
249   int32 ring_buffer_size_;
250   Buffer ring_buffer_;
251   CommandBufferEntry* entries_;
252   int32 total_entry_count_;  // the total number of entries
253   int32 token_;
254   int32 put_;
255   int32 last_put_sent_;
256   int commands_issued_;
257   bool usable_;
258   bool context_lost_;
259   bool flush_automatically_;
260 
261   // Using C runtime instead of base because this file cannot depend on base.
262   clock_t last_flush_time_;
263 
264   friend class CommandBufferHelperTest;
265   DISALLOW_COPY_AND_ASSIGN(CommandBufferHelper);
266 };
267 
268 }  // namespace gpu
269 
270 #endif  // GPU_COMMAND_BUFFER_CLIENT_CMD_BUFFER_HELPER_H_
271