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

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

Issue 7253052: Execute all GL commands up to the put offset reported by a flush. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 5 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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 #include "../common/trace_event.h" 9 #include "../common/trace_event.h"
10 10
11 namespace gpu { 11 namespace gpu {
12 12
13 CommandBufferHelper::CommandBufferHelper(CommandBuffer* command_buffer) 13 CommandBufferHelper::CommandBufferHelper(CommandBuffer* command_buffer)
14 : command_buffer_(command_buffer), 14 : command_buffer_(command_buffer),
15 entries_(NULL), 15 entries_(NULL),
16 total_entry_count_(0), 16 total_entry_count_(0),
17 usable_entry_count_(0), 17 usable_entry_count_(0),
18 token_(0), 18 token_(0),
19 last_token_read_(-1),
20 get_(0),
21 put_(0), 19 put_(0),
22 last_put_sent_(0) { 20 last_put_sent_(0) {
23 } 21 }
24 22
25 bool CommandBufferHelper::Initialize(int32 ring_buffer_size) { 23 bool CommandBufferHelper::Initialize(int32 ring_buffer_size) {
26 ring_buffer_ = command_buffer_->GetRingBuffer(); 24 ring_buffer_ = command_buffer_->GetRingBuffer();
27 if (!ring_buffer_.ptr) 25 if (!ring_buffer_.ptr)
28 return false; 26 return false;
29 27
30 CommandBuffer::State state = command_buffer_->GetState(); 28 CommandBuffer::State state = command_buffer_->GetState();
31 entries_ = static_cast<CommandBufferEntry*>(ring_buffer_.ptr); 29 entries_ = static_cast<CommandBufferEntry*>(ring_buffer_.ptr);
32 int32 num_ring_buffer_entries = ring_buffer_size / sizeof(CommandBufferEntry); 30 int32 num_ring_buffer_entries = ring_buffer_size / sizeof(CommandBufferEntry);
33 if (num_ring_buffer_entries > state.num_entries) { 31 if (num_ring_buffer_entries > state.num_entries) {
34 return false; 32 return false;
35 } 33 }
36 34
37 const int32 kJumpEntries = 35 const int32 kJumpEntries =
38 sizeof(cmd::Jump) / sizeof(*entries_); // NOLINT 36 sizeof(cmd::Jump) / sizeof(*entries_); // NOLINT
39 37
40 total_entry_count_ = num_ring_buffer_entries; 38 total_entry_count_ = num_ring_buffer_entries;
41 usable_entry_count_ = total_entry_count_ - kJumpEntries; 39 usable_entry_count_ = total_entry_count_ - kJumpEntries;
42 put_ = state.put_offset; 40 put_ = state.put_offset;
43 SynchronizeState(state);
44 return true; 41 return true;
45 } 42 }
46 43
47 CommandBufferHelper::~CommandBufferHelper() { 44 CommandBufferHelper::~CommandBufferHelper() {
48 } 45 }
49 46
50 bool CommandBufferHelper::FlushSync() { 47 bool CommandBufferHelper::FlushSync() {
51 last_put_sent_ = put_; 48 last_put_sent_ = put_;
52 CommandBuffer::State state = command_buffer_->FlushSync(put_, get_); 49 CommandBuffer::State state = command_buffer_->FlushSync(put_, get_offset());
53 SynchronizeState(state);
54 return state.error == error::kNoError; 50 return state.error == error::kNoError;
55 } 51 }
56 52
57 void CommandBufferHelper::Flush() { 53 void CommandBufferHelper::Flush() {
58 last_put_sent_ = put_; 54 last_put_sent_ = put_;
59 command_buffer_->Flush(put_); 55 command_buffer_->Flush(put_);
60 } 56 }
61 57
62 // Calls Flush() and then waits until the buffer is empty. Break early if the 58 // Calls Flush() and then waits until the buffer is empty. Break early if the
63 // error is set. 59 // error is set.
64 bool CommandBufferHelper::Finish() { 60 bool CommandBufferHelper::Finish() {
65 TRACE_EVENT0("gpu", "CommandBufferHelper::Finish"); 61 TRACE_EVENT0("gpu", "CommandBufferHelper::Finish");
66 do { 62 do {
67 // Do not loop forever if the flush fails, meaning the command buffer reader 63 // Do not loop forever if the flush fails, meaning the command buffer reader
68 // has shutdown. 64 // has shutdown.
69 if (!FlushSync()) 65 if (!FlushSync())
70 return false; 66 return false;
71 } while (put_ != get_); 67 } while (put_ != get_offset());
72 68
73 return true; 69 return true;
74 } 70 }
75 71
76 // Inserts a new token into the command stream. It uses an increasing value 72 // Inserts a new token into the command stream. It uses an increasing value
77 // scheme so that we don't lose tokens (a token has passed if the current token 73 // scheme so that we don't lose tokens (a token has passed if the current token
78 // value is higher than that token). Calls Finish() if the token value wraps, 74 // value is higher than that token). Calls Finish() if the token value wraps,
79 // which will be rare. 75 // which will be rare.
80 int32 CommandBufferHelper::InsertToken() { 76 int32 CommandBufferHelper::InsertToken() {
81 // Increment token as 31-bit integer. Negative values are used to signal an 77 // Increment token as 31-bit integer. Negative values are used to signal an
82 // error. 78 // error.
83 token_ = (token_ + 1) & 0x7FFFFFFF; 79 token_ = (token_ + 1) & 0x7FFFFFFF;
84 cmd::SetToken& cmd = GetCmdSpace<cmd::SetToken>(); 80 cmd::SetToken& cmd = GetCmdSpace<cmd::SetToken>();
85 cmd.Init(token_); 81 cmd.Init(token_);
86 if (token_ == 0) { 82 if (token_ == 0) {
87 TRACE_EVENT0("gpu", "CommandBufferHelper::InsertToken(wrapped)"); 83 TRACE_EVENT0("gpu", "CommandBufferHelper::InsertToken(wrapped)");
88 // we wrapped 84 // we wrapped
89 Finish(); 85 Finish();
90 GPU_DCHECK_EQ(token_, last_token_read_); 86 GPU_DCHECK_EQ(token_, last_token_read());
91 } 87 }
92 return token_; 88 return token_;
93 } 89 }
94 90
95 // Waits until the current token value is greater or equal to the value passed 91 // Waits until the current token value is greater or equal to the value passed
96 // in argument. 92 // in argument.
97 void CommandBufferHelper::WaitForToken(int32 token) { 93 void CommandBufferHelper::WaitForToken(int32 token) {
98 TRACE_EVENT_IF_LONGER_THAN0(50, "gpu", "CommandBufferHelper::WaitForToken"); 94 TRACE_EVENT_IF_LONGER_THAN0(50, "gpu", "CommandBufferHelper::WaitForToken");
99 // Return immediately if corresponding InsertToken failed. 95 // Return immediately if corresponding InsertToken failed.
100 if (token < 0) 96 if (token < 0)
101 return; 97 return;
102 if (token > token_) return; // we wrapped 98 if (token > token_) return; // we wrapped
103 while (last_token_read_ < token) { 99 while (last_token_read() < token) {
104 if (get_ == put_) { 100 if (get_offset() == put_) {
105 GPU_LOG(FATAL) << "Empty command buffer while waiting on a token."; 101 GPU_LOG(FATAL) << "Empty command buffer while waiting on a token.";
106 return; 102 return;
107 } 103 }
108 // 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
109 // has shutdown. 105 // has shutdown.
110 if (!FlushSync()) 106 if (!FlushSync())
111 return; 107 return;
112 } 108 }
113 } 109 }
114 110
115 void CommandBufferHelper::YieldScheduler() {
116 cmd::YieldScheduler& cmd = GetCmdSpace<cmd::YieldScheduler>();
117 cmd.Init();
118 }
119
120 // Waits for available entries, basically waiting until get >= put + count + 1. 111 // Waits for available entries, basically waiting until get >= put + count + 1.
121 // 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
122 // 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
123 // 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
124 // space may not be available. 115 // space may not be available.
125 void CommandBufferHelper::WaitForAvailableEntries(int32 count) { 116 void CommandBufferHelper::WaitForAvailableEntries(int32 count) {
126 GPU_DCHECK(count < usable_entry_count_); 117 GPU_DCHECK(count < usable_entry_count_);
127 if (put_ + count > usable_entry_count_) { 118 if (put_ + count > usable_entry_count_) {
128 // 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
129 // 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
130 // 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
131 // put will wrap to 0 after we add the jump). 122 // put will wrap to 0 after we add the jump).
132 GPU_DCHECK_LE(1, put_); 123 GPU_DCHECK_LE(1, put_);
133 if (get_ > put_ || get_ == 0) { 124 if (get_offset() > put_ || get_offset() == 0) {
134 TRACE_EVENT0("gpu", "CommandBufferHelper::WaitForAvailableEntries"); 125 TRACE_EVENT0("gpu", "CommandBufferHelper::WaitForAvailableEntries");
135 while (get_ > put_ || get_ == 0) { 126 while (get_offset() > put_ || get_offset() == 0) {
136 // Do not loop forever if the flush fails, meaning the command buffer 127 // Do not loop forever if the flush fails, meaning the command buffer
137 // reader has shutdown. 128 // reader has shutdown.
138 if (!FlushSync()) 129 if (!FlushSync())
139 return; 130 return;
140 } 131 }
141 } 132 }
142 // Insert a jump back to the beginning. 133 // Insert a jump back to the beginning.
143 cmd::Jump::Set(&entries_[put_], 0); 134 cmd::Jump::Set(&entries_[put_], 0);
144 put_ = 0; 135 put_ = 0;
145 } 136 }
146 if (AvailableEntries() < count) { 137 if (AvailableEntries() < count) {
147 TRACE_EVENT0("gpu", "CommandBufferHelper::WaitForAvailableEntries1"); 138 TRACE_EVENT0("gpu", "CommandBufferHelper::WaitForAvailableEntries1");
148 while (AvailableEntries() < count) { 139 while (AvailableEntries() < count) {
jbates 2011/07/11 18:39:50 Looks like this loop is no longer needed because o
apatrick_chromium 2011/07/11 21:25:45 It should actually be a FlushSync. Fixed.
149 // Do not loop forever if the flush fails, meaning the command buffer 140 // Do not loop forever if the flush fails, meaning the command buffer
150 // reader has shutdown. 141 // reader has shutdown.
151 if (!FlushSync()) 142 if (!Finish())
152 return; 143 return;
153 } 144 }
154 } 145 }
155 // Force a flush if the buffer is getting half full, or even earlier if the 146 // Force a flush if the buffer is getting half full, or even earlier if the
156 // reader is known to be idle. 147 // reader is known to be idle.
157 int32 pending = 148 int32 pending =
158 (put_ + usable_entry_count_ - last_put_sent_) % usable_entry_count_; 149 (put_ + usable_entry_count_ - last_put_sent_) % usable_entry_count_;
159 int32 limit = usable_entry_count_ / ((get_ == last_put_sent_) ? 16 : 2); 150 int32 limit = usable_entry_count_ /
151 ((get_offset() == last_put_sent_) ? 16 : 2);
160 if (pending > limit) { 152 if (pending > limit) {
161 Flush(); 153 Flush();
162 } 154 }
163 } 155 }
164 156
165 CommandBufferEntry* CommandBufferHelper::GetSpace(uint32 entries) { 157 CommandBufferEntry* CommandBufferHelper::GetSpace(uint32 entries) {
166 WaitForAvailableEntries(entries); 158 WaitForAvailableEntries(entries);
167 CommandBufferEntry* space = &entries_[put_]; 159 CommandBufferEntry* space = &entries_[put_];
168 put_ += entries; 160 put_ += entries;
169 GPU_DCHECK_LE(put_, usable_entry_count_); 161 GPU_DCHECK_LE(put_, usable_entry_count_);
170 if (put_ == usable_entry_count_) { 162 if (put_ == usable_entry_count_) {
171 cmd::Jump::Set(&entries_[put_], 0); 163 cmd::Jump::Set(&entries_[put_], 0);
172 put_ = 0; 164 put_ = 0;
173 } 165 }
174 return space; 166 return space;
175 } 167 }
176 168
177 error::Error CommandBufferHelper::GetError() { 169 error::Error CommandBufferHelper::GetError() {
178 CommandBuffer::State state = command_buffer_->GetState(); 170 CommandBuffer::State state = command_buffer_->GetState();
179 SynchronizeState(state);
180 return static_cast<error::Error>(state.error); 171 return static_cast<error::Error>(state.error);
181 } 172 }
182 173
183 void CommandBufferHelper::SynchronizeState(const CommandBuffer::State& state) {
184 get_ = state.get_offset;
185 last_token_read_ = state.token;
186 }
187
188 } // namespace gpu 174 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698