Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(72)

Side by Side Diff: gpu/command_buffer/client/cmd_buffer_helper.cc

Issue 6316002: Make CommandBuffer::Flush asynchronous, and add CommandBuffer::FlushSync with former semantics. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // This file contains the implementation of the command buffer helper class. 5 // This file contains the implementation of the command buffer helper class.
6 6
7 #include "../client/cmd_buffer_helper.h" 7 #include "../client/cmd_buffer_helper.h"
8 #include "../common/command_buffer.h" 8 #include "../common/command_buffer.h"
9 9
10 namespace gpu { 10 namespace gpu {
11 11
12 CommandBufferHelper::CommandBufferHelper(CommandBuffer* command_buffer) 12 CommandBufferHelper::CommandBufferHelper(CommandBuffer* command_buffer)
13 : command_buffer_(command_buffer), 13 : command_buffer_(command_buffer),
14 entries_(NULL), 14 entries_(NULL),
15 total_entry_count_(0), 15 total_entry_count_(0),
16 usable_entry_count_(0), 16 usable_entry_count_(0),
17 token_(0), 17 token_(0),
18 last_token_read_(-1), 18 last_token_read_(-1),
19 get_(0), 19 get_(0),
20 put_(0) { 20 put_(0),
21 last_put_sent_(0) {
21 } 22 }
22 23
23 bool CommandBufferHelper::Initialize(int32 ring_buffer_size) { 24 bool CommandBufferHelper::Initialize(int32 ring_buffer_size) {
24 ring_buffer_ = command_buffer_->GetRingBuffer(); 25 ring_buffer_ = command_buffer_->GetRingBuffer();
25 if (!ring_buffer_.ptr) 26 if (!ring_buffer_.ptr)
26 return false; 27 return false;
27 28
28 CommandBuffer::State state = command_buffer_->GetState(); 29 CommandBuffer::State state = command_buffer_->GetState();
29 entries_ = static_cast<CommandBufferEntry*>(ring_buffer_.ptr); 30 entries_ = static_cast<CommandBufferEntry*>(ring_buffer_.ptr);
30 int32 num_ring_buffer_entries = ring_buffer_size / sizeof(CommandBufferEntry); 31 int32 num_ring_buffer_entries = ring_buffer_size / sizeof(CommandBufferEntry);
31 if (num_ring_buffer_entries > state.num_entries) { 32 if (num_ring_buffer_entries > state.num_entries) {
32 return false; 33 return false;
33 } 34 }
34 35
35 const int32 kJumpEntries = 36 const int32 kJumpEntries =
36 sizeof(cmd::Jump) / sizeof(*entries_); // NOLINT 37 sizeof(cmd::Jump) / sizeof(*entries_); // NOLINT
37 38
38 total_entry_count_ = num_ring_buffer_entries; 39 total_entry_count_ = num_ring_buffer_entries;
39 usable_entry_count_ = total_entry_count_ - kJumpEntries; 40 usable_entry_count_ = total_entry_count_ - kJumpEntries;
40 put_ = state.put_offset; 41 put_ = state.put_offset;
41 SynchronizeState(state); 42 SynchronizeState(state);
42 return true; 43 return true;
43 } 44 }
44 45
45 CommandBufferHelper::~CommandBufferHelper() { 46 CommandBufferHelper::~CommandBufferHelper() {
46 } 47 }
47 48
48 bool CommandBufferHelper::Flush() { 49 bool CommandBufferHelper::FlushSync() {
49 CommandBuffer::State state = command_buffer_->Flush(put_); 50 last_put_sent_ = put_;
51 CommandBuffer::State state = command_buffer_->FlushSync(put_);
50 SynchronizeState(state); 52 SynchronizeState(state);
51 return state.error == error::kNoError; 53 return state.error == error::kNoError;
52 } 54 }
53 55
56 void CommandBufferHelper::Flush() {
57 last_put_sent_ = put_;
58 command_buffer_->Flush(put_);
59 }
60
54 // Calls Flush() and then waits until the buffer is empty. Break early if the 61 // Calls Flush() and then waits until the buffer is empty. Break early if the
55 // error is set. 62 // error is set.
56 bool CommandBufferHelper::Finish() { 63 bool CommandBufferHelper::Finish() {
57 do { 64 do {
58 // Do not loop forever if the flush fails, meaning the command buffer reader 65 // Do not loop forever if the flush fails, meaning the command buffer reader
59 // has shutdown. 66 // has shutdown.
60 if (!Flush()) 67 if (!FlushSync())
61 return false; 68 return false;
62 } while (put_ != get_); 69 } while (put_ != get_);
63 70
64 return true; 71 return true;
65 } 72 }
66 73
67 // Inserts a new token into the command stream. It uses an increasing value 74 // Inserts a new token into the command stream. It uses an increasing value
68 // scheme so that we don't lose tokens (a token has passed if the current token 75 // scheme so that we don't lose tokens (a token has passed if the current token
69 // value is higher than that token). Calls Finish() if the token value wraps, 76 // value is higher than that token). Calls Finish() if the token value wraps,
70 // which will be rare. 77 // which will be rare.
(...skipping 10 matching lines...) Expand all
81 } 88 }
82 return token_; 89 return token_;
83 } 90 }
84 91
85 // Waits until the current token value is greater or equal to the value passed 92 // Waits until the current token value is greater or equal to the value passed
86 // in argument. 93 // in argument.
87 void CommandBufferHelper::WaitForToken(int32 token) { 94 void CommandBufferHelper::WaitForToken(int32 token) {
88 // Return immediately if corresponding InsertToken failed. 95 // Return immediately if corresponding InsertToken failed.
89 if (token < 0) 96 if (token < 0)
90 return; 97 return;
91 if (last_token_read_ >= token) return; // fast path.
92 if (token > token_) return; // we wrapped 98 if (token > token_) return; // we wrapped
93 Flush();
94 while (last_token_read_ < token) { 99 while (last_token_read_ < token) {
95 if (get_ == put_) { 100 if (get_ == put_) {
96 GPU_LOG(FATAL) << "Empty command buffer while waiting on a token."; 101 GPU_LOG(FATAL) << "Empty command buffer while waiting on a token.";
97 return; 102 return;
98 } 103 }
99 // Do not loop forever if the flush fails, meaning the command buffer reader 104 // Do not loop forever if the flush fails, meaning the command buffer reader
100 // has shutdown. 105 // has shutdown.
101 if (!Flush()) 106 if (!FlushSync())
102 return; 107 return;
103 } 108 }
104 } 109 }
105 110
106 // Waits for available entries, basically waiting until get >= put + count + 1. 111 // Waits for available entries, basically waiting until get >= put + count + 1.
107 // It actually waits for contiguous entries, so it may need to wrap the buffer 112 // It actually waits for contiguous entries, so it may need to wrap the buffer
108 // around, adding a jump. Thus this function may change the value of put_. The 113 // around, adding a jump. Thus this function may change the value of put_. The
109 // function will return early if an error occurs, in which case the available 114 // function will return early if an error occurs, in which case the available
110 // space may not be available. 115 // space may not be available.
111 void CommandBufferHelper::WaitForAvailableEntries(int32 count) { 116 void CommandBufferHelper::WaitForAvailableEntries(int32 count) {
112 GPU_CHECK(count < usable_entry_count_); 117 GPU_CHECK(count < usable_entry_count_);
113 if (put_ + count > usable_entry_count_) { 118 if (put_ + count > usable_entry_count_) {
114 // There's not enough room between the current put and the end of the 119 // There's not enough room between the current put and the end of the
115 // buffer, so we need to wrap. We will add a jump back to the start, but we 120 // buffer, so we need to wrap. We will add a jump back to the start, but we
116 // need to make sure get wraps first, actually that get is 1 or more (since 121 // need to make sure get wraps first, actually that get is 1 or more (since
117 // put will wrap to 0 after we add the jump). 122 // put will wrap to 0 after we add the jump).
118 GPU_DCHECK_LE(1, put_); 123 GPU_DCHECK_LE(1, put_);
119 Flush();
120 while (get_ > put_ || get_ == 0) { 124 while (get_ > put_ || get_ == 0) {
121 // Do not loop forever if the flush fails, meaning the command buffer 125 // Do not loop forever if the flush fails, meaning the command buffer
122 // reader has shutdown. 126 // reader has shutdown.
123 if (!Flush()) 127 if (!FlushSync())
124 return; 128 return;
125 } 129 }
126 // Insert a jump back to the beginning. 130 // Insert a jump back to the beginning.
127 cmd::Jump::Set(&entries_[put_], 0); 131 cmd::Jump::Set(&entries_[put_], 0);
128 put_ = 0; 132 put_ = 0;
129 } 133 }
130 // If we have enough room, return immediatly.
131 if (count <= AvailableEntries()) return;
132 // Otherwise flush, and wait until we do have enough room.
133 Flush();
134 while (AvailableEntries() < count) { 134 while (AvailableEntries() < count) {
135 // Do not loop forever if the flush fails, meaning the command buffer reader 135 // Do not loop forever if the flush fails, meaning the command buffer reader
136 // has shutdown. 136 // has shutdown.
137 if (!Flush()) 137 if (!FlushSync())
138 return; 138 return;
139 } 139 }
140 // Force a flush if the buffer is getting half full, or even earlier if the
141 // reader is know to be idle.
apatrick_chromium 2011/01/14 22:43:32 know -> known
Antoine Labour 2011/01/14 23:17:28 Done.
142 int32 pending =
143 (put_ + usable_entry_count_ - last_put_sent_) % usable_entry_count_;
144 int32 limit = usable_entry_count_ / ((get_ == last_put_sent_) ? 16 : 2);
145 if (pending > limit) {
146 Flush();
147 }
140 } 148 }
141 149
142 CommandBufferEntry* CommandBufferHelper::GetSpace(uint32 entries) { 150 CommandBufferEntry* CommandBufferHelper::GetSpace(uint32 entries) {
143 WaitForAvailableEntries(entries); 151 WaitForAvailableEntries(entries);
144 CommandBufferEntry* space = &entries_[put_]; 152 CommandBufferEntry* space = &entries_[put_];
145 put_ += entries; 153 put_ += entries;
146 GPU_DCHECK_LE(put_, usable_entry_count_); 154 GPU_DCHECK_LE(put_, usable_entry_count_);
147 if (put_ == usable_entry_count_) { 155 if (put_ == usable_entry_count_) {
148 cmd::Jump::Set(&entries_[put_], 0); 156 cmd::Jump::Set(&entries_[put_], 0);
149 put_ = 0; 157 put_ = 0;
150 } 158 }
151 return space; 159 return space;
152 } 160 }
153 161
154 error::Error CommandBufferHelper::GetError() { 162 error::Error CommandBufferHelper::GetError() {
155 CommandBuffer::State state = command_buffer_->GetState(); 163 CommandBuffer::State state = command_buffer_->GetState();
156 SynchronizeState(state); 164 SynchronizeState(state);
157 return static_cast<error::Error>(state.error); 165 return static_cast<error::Error>(state.error);
158 } 166 }
159 167
160 void CommandBufferHelper::SynchronizeState(CommandBuffer::State state) { 168 void CommandBufferHelper::SynchronizeState(CommandBuffer::State state) {
161 get_ = state.get_offset; 169 get_ = state.get_offset;
162 last_token_read_ = state.token; 170 last_token_read_ = state.token;
163 } 171 }
164 172
165 } // namespace gpu 173 } // namespace gpu
OLDNEW
« no previous file with comments | « gpu/command_buffer/client/cmd_buffer_helper.h ('k') | gpu/command_buffer/client/gles2_implementation_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698