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.
5 // This file contains the command buffer helper class.
7 #ifndef GPU_COMMAND_BUFFER_CLIENT_CMD_BUFFER_HELPER_H_
8 #define GPU_COMMAND_BUFFER_CLIENT_CMD_BUFFER_HELPER_H_
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"
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:
26 // helper.AddCommand(...);
27 // helper.AddCommand(...);
28 // int32 token = helper.InsertToken();
29 // helper.AddCommand(...);
30 // helper.AddCommand(...);
33 // helper.WaitForToken(token); // this doesn't return until the first two
34 // // commands have been executed.
35 class GPU_EXPORT CommandBufferHelper {
37 explicit CommandBufferHelper(CommandBuffer* command_buffer);
38 virtual ~CommandBufferHelper();
40 // Initializes the CommandBufferHelper.
42 // ring_buffer_size: The size of the ring buffer portion of the command
44 bool Initialize(int32 ring_buffer_size);
46 // Sets whether the command buffer should automatically flush periodically
47 // to try to increase performance. Defaults to true.
48 void SetAutomaticFlushes(bool enabled);
50 // True if the context is lost.
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.
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
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
71 // Waits until a given number of available entries are available.
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);
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
82 // the value of the new token or -1 if the command buffer reader has
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.
90 // the value of the token to wait for.
91 void WaitForToken(int32 token);
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);
97 // Typed version of GetSpace. Gets enough room for the given type and returns
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);
107 // Typed version of GetSpace for immediate commands.
108 template <typename T>
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);
116 // Typed version of GetSpace for immediate commands.
117 template <typename T>
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);
125 int32 last_token_read() const {
126 return command_buffer_->GetLastToken();
129 int32 get_offset() const {
130 return command_buffer_->GetLastState().get_offset;
134 void Noop(uint32 skip_count) {
135 cmd::Noop* cmd = GetImmediateCmdSpace<cmd::Noop>(
136 (skip_count - 1) * sizeof(CommandBufferEntry));
138 cmd->Init(skip_count);
142 void SetToken(uint32 token) {
143 cmd::SetToken* cmd = GetCmdSpace<cmd::SetToken>();
149 void SetBucketSize(uint32 bucket_id, uint32 size) {
150 cmd::SetBucketSize* cmd = GetCmdSpace<cmd::SetBucketSize>();
152 cmd->Init(bucket_id, size);
156 void SetBucketData(uint32 bucket_id,
159 uint32 shared_memory_id,
160 uint32 shared_memory_offset) {
161 cmd::SetBucketData* cmd = GetCmdSpace<cmd::SetBucketData>();
167 shared_memory_offset);
171 void SetBucketDataImmediate(
172 uint32 bucket_id, uint32 offset, const void* data, uint32 size) {
173 cmd::SetBucketDataImmediate* cmd =
174 GetImmediateCmdSpace<cmd::SetBucketDataImmediate>(size);
176 cmd->Init(bucket_id, offset, size);
177 memcpy(ImmediateDataAddress(cmd), data, size);
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>();
191 result_memory_offset,
198 void GetBucketData(uint32 bucket_id,
201 uint32 shared_memory_id,
202 uint32 shared_memory_offset) {
203 cmd::GetBucketData* cmd = GetCmdSpace<cmd::GetBucketData>();
209 shared_memory_offset);
213 CommandBuffer* command_buffer() const {
214 return command_buffer_;
217 Buffer get_ring_buffer() const {
221 void FreeRingBuffer();
223 bool HaveRingBuffer() const {
224 return ring_buffer_id_ != -1;
227 bool usable () const {
236 // Waits until get changes, updating the value of get_.
237 void WaitForGetChange();
239 // Returns the number of available entries (they may not be contiguous).
240 int32 AvailableEntries() {
241 return (get_offset() - put_ - 1 + total_entry_count_) % total_entry_count_;
244 bool AllocateRingBuffer();
245 void FreeResources();
247 CommandBuffer* command_buffer_;
248 int32 ring_buffer_id_;
249 int32 ring_buffer_size_;
251 CommandBufferEntry* entries_;
252 int32 total_entry_count_; // the total number of entries
255 int32 last_put_sent_;
256 int commands_issued_;
259 bool flush_automatically_;
261 // Using C runtime instead of base because this file cannot depend on base.
262 clock_t last_flush_time_;
264 friend class CommandBufferHelperTest;
265 DISALLOW_COPY_AND_ASSIGN(CommandBufferHelper);
270 #endif // GPU_COMMAND_BUFFER_CLIENT_CMD_BUFFER_HELPER_H_