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

Side by Side Diff: gpu/command_buffer/service/cmd_parser_test.cc

Issue 558513003: command_buffer: Batch command processing to reduce handler overheads. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 6 years, 3 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
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 // Tests for the command parser. 5 // Tests for the command parser.
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h" 8 #include "base/memory/scoped_ptr.h"
9 #include "gpu/command_buffer/service/cmd_parser.h" 9 #include "gpu/command_buffer/service/cmd_parser.h"
10 #include "gpu/command_buffer/service/mocks.h" 10 #include "gpu/command_buffer/service/mocks.h"
11 #include "testing/gtest/include/gtest/gtest.h" 11 #include "testing/gtest/include/gtest/gtest.h"
12 12
13 namespace gpu { 13 namespace gpu {
14 14
15 using testing::_;
16 using testing::Invoke;
17 using testing::Mock;
15 using testing::Return; 18 using testing::Return;
16 using testing::Mock; 19 using testing::Sequence;
20 using testing::SetArgPointee;
17 using testing::Truly; 21 using testing::Truly;
18 using testing::Sequence;
19 using testing::_;
20 22
21 // Test fixture for CommandParser test - Creates a mock AsyncAPIInterface, and 23 // Test fixture for CommandParser test - Creates a mock AsyncAPIInterface, and
22 // a fixed size memory buffer. Also provides a simple API to create a 24 // a fixed size memory buffer. Also provides a simple API to create a
23 // CommandParser. 25 // CommandParser.
24 class CommandParserTest : public testing::Test { 26 class CommandParserTest : public testing::Test {
25 protected: 27 protected:
26 virtual void SetUp() { 28 virtual void SetUp() {
27 api_mock_.reset(new AsyncAPIMock); 29 api_mock_.reset(new AsyncAPIMock(false));
28 buffer_entry_count_ = 20; 30 buffer_entry_count_ = 20;
29 buffer_.reset(new CommandBufferEntry[buffer_entry_count_]); 31 buffer_.reset(new CommandBufferEntry[buffer_entry_count_]);
30 } 32 }
31 virtual void TearDown() {} 33 virtual void TearDown() {}
32 34
33 // Adds a DoCommand expectation in the mock. 35 void AddDoCommandsExpect(error::Error _return,
34 void AddDoCommandExpect(error::Error _return, 36 unsigned int num_commands,
35 unsigned int command, 37 int num_entries,
36 unsigned int arg_count, 38 int num_processed) {
37 CommandBufferEntry *args) { 39 EXPECT_CALL(*api_mock_, DoCommands(num_commands, _, num_entries, _))
38 EXPECT_CALL(*api_mock(), DoCommand(command, arg_count,
39 Truly(AsyncAPIMock::IsArgs(arg_count, args))))
40 .InSequence(sequence_) 40 .InSequence(sequence_)
41 .WillOnce(Return(_return)); 41 .WillOnce(DoAll(SetArgPointee<3>(num_processed), Return(_return)));
42 } 42 }
43 43
44 // Creates a parser, with a buffer of the specified size (in entries). 44 // Creates a parser, with a buffer of the specified size (in entries).
45 CommandParser *MakeParser(unsigned int entry_count) { 45 CommandParser *MakeParser(unsigned int entry_count) {
46 size_t shm_size = buffer_entry_count_ * 46 size_t shm_size = buffer_entry_count_ *
47 sizeof(CommandBufferEntry); // NOLINT 47 sizeof(CommandBufferEntry); // NOLINT
48 size_t command_buffer_size = entry_count * 48 size_t command_buffer_size = entry_count *
49 sizeof(CommandBufferEntry); // NOLINT 49 sizeof(CommandBufferEntry); // NOLINT
50 DCHECK_LE(command_buffer_size, shm_size); 50 DCHECK_LE(command_buffer_size, shm_size);
51 CommandParser* parser = new CommandParser(api_mock()); 51 CommandParser* parser = new CommandParser(api_mock());
(...skipping 23 matching lines...) Expand all
75 // Tests simple commands. 75 // Tests simple commands.
76 TEST_F(CommandParserTest, TestSimple) { 76 TEST_F(CommandParserTest, TestSimple) {
77 scoped_ptr<CommandParser> parser(MakeParser(10)); 77 scoped_ptr<CommandParser> parser(MakeParser(10));
78 CommandBufferOffset put = parser->put(); 78 CommandBufferOffset put = parser->put();
79 CommandHeader header; 79 CommandHeader header;
80 80
81 // add a single command, no args 81 // add a single command, no args
82 header.size = 1; 82 header.size = 1;
83 header.command = 123; 83 header.command = 123;
84 buffer()[put++].value_header = header; 84 buffer()[put++].value_header = header;
85
86 parser->set_put(put); 85 parser->set_put(put);
87 EXPECT_EQ(put, parser->put()); 86 EXPECT_EQ(put, parser->put());
88 87
89 AddDoCommandExpect(error::kNoError, 123, 0, NULL); 88 AddDoCommandsExpect(error::kNoError, 1, 1, 1);
90 EXPECT_EQ(error::kNoError, parser->ProcessCommand()); 89 EXPECT_EQ(error::kNoError, parser->ProcessCommands(1));
91 EXPECT_EQ(put, parser->get()); 90 EXPECT_EQ(put, parser->get());
92 Mock::VerifyAndClearExpectations(api_mock()); 91 Mock::VerifyAndClearExpectations(api_mock());
93 92
94 // add a single command, 2 args 93 // add a single command, 2 args
95 header.size = 3; 94 header.size = 3;
96 header.command = 456; 95 header.command = 456;
97 buffer()[put++].value_header = header; 96 buffer()[put++].value_header = header;
98 buffer()[put++].value_int32 = 2134; 97 buffer()[put++].value_int32 = 2134;
99 buffer()[put++].value_float = 1.f; 98 buffer()[put++].value_float = 1.f;
100
101 parser->set_put(put); 99 parser->set_put(put);
102 EXPECT_EQ(put, parser->put()); 100 EXPECT_EQ(put, parser->put());
103 101
104 CommandBufferEntry param_array[2]; 102 AddDoCommandsExpect(error::kNoError, 1, 3, 3);
105 param_array[0].value_int32 = 2134; 103 EXPECT_EQ(error::kNoError, parser->ProcessCommands(1));
106 param_array[1].value_float = 1.f;
107 AddDoCommandExpect(error::kNoError, 456, 2, param_array);
108 EXPECT_EQ(error::kNoError, parser->ProcessCommand());
109 EXPECT_EQ(put, parser->get()); 104 EXPECT_EQ(put, parser->get());
110 Mock::VerifyAndClearExpectations(api_mock()); 105 Mock::VerifyAndClearExpectations(api_mock());
111 } 106 }
112 107
113 // Tests having multiple commands in the buffer. 108 // Tests having multiple commands in the buffer.
114 TEST_F(CommandParserTest, TestMultipleCommands) { 109 TEST_F(CommandParserTest, TestMultipleCommands) {
115 scoped_ptr<CommandParser> parser(MakeParser(10)); 110 scoped_ptr<CommandParser> parser(MakeParser(10));
116 CommandBufferOffset put = parser->put(); 111 CommandBufferOffset put = parser->put();
117 CommandHeader header; 112 CommandHeader header;
118 113
119 // add 2 commands, test with single ProcessCommand() 114 // add 2 commands, test with single ProcessCommands()
120 header.size = 2; 115 header.size = 2;
121 header.command = 789; 116 header.command = 789;
122 buffer()[put++].value_header = header; 117 buffer()[put++].value_header = header;
123 buffer()[put++].value_int32 = 5151; 118 buffer()[put++].value_int32 = 5151;
124 119
125 CommandBufferOffset put_cmd2 = put; 120 CommandBufferOffset put_cmd2 = put;
126 header.size = 2; 121 header.size = 2;
127 header.command = 876; 122 header.command = 876;
128 buffer()[put++].value_header = header; 123 buffer()[put++].value_header = header;
129 buffer()[put++].value_int32 = 3434; 124 buffer()[put++].value_int32 = 3434;
130
131 parser->set_put(put); 125 parser->set_put(put);
132 EXPECT_EQ(put, parser->put()); 126 EXPECT_EQ(put, parser->put());
133 127
134 CommandBufferEntry param_array[2]; 128 // Process up to 1 command. 4 entries remaining.
135 param_array[0].value_int32 = 5151; 129 AddDoCommandsExpect(error::kNoError, 1, 4, 2);
136 AddDoCommandExpect(error::kNoError, 789, 1, param_array); 130 EXPECT_EQ(error::kNoError, parser->ProcessCommands(1));
137 param_array[1].value_int32 = 3434; 131 EXPECT_EQ(put_cmd2, parser->get());
138 AddDoCommandExpect(error::kNoError, 876, 1,
139 param_array+1);
140 132
141 EXPECT_EQ(error::kNoError, parser->ProcessCommand()); 133 // Process up to 1 command. 2 entries remaining.
142 EXPECT_EQ(put_cmd2, parser->get()); 134 AddDoCommandsExpect(error::kNoError, 1, 2, 2);
143 EXPECT_EQ(error::kNoError, parser->ProcessCommand()); 135 EXPECT_EQ(error::kNoError, parser->ProcessCommands(1));
144 EXPECT_EQ(put, parser->get()); 136 EXPECT_EQ(put, parser->get());
145 Mock::VerifyAndClearExpectations(api_mock()); 137 Mock::VerifyAndClearExpectations(api_mock());
146 138
147 // add 2 commands again, test with ProcessAllCommands() 139 // add 2 commands again, test with ProcessAllCommands()
148 header.size = 2; 140 header.size = 2;
149 header.command = 123; 141 header.command = 123;
150 buffer()[put++].value_header = header; 142 buffer()[put++].value_header = header;
151 buffer()[put++].value_int32 = 5656; 143 buffer()[put++].value_int32 = 5656;
152 144
153 header.size = 2; 145 header.size = 2;
154 header.command = 321; 146 header.command = 321;
155 buffer()[put++].value_header = header; 147 buffer()[put++].value_header = header;
156 buffer()[put++].value_int32 = 7878; 148 buffer()[put++].value_int32 = 7878;
157
158 parser->set_put(put); 149 parser->set_put(put);
159 EXPECT_EQ(put, parser->put()); 150 EXPECT_EQ(put, parser->put());
160 151
161 param_array[0].value_int32 = 5656; 152 // 4 entries remaining.
162 AddDoCommandExpect(error::kNoError, 123, 1, param_array); 153 AddDoCommandsExpect(
163 param_array[1].value_int32 = 7878; 154 error::kNoError, CommandParser::kParseCommandsSlice, 4, 4);
164 AddDoCommandExpect(error::kNoError, 321, 1,
165 param_array+1);
166
167 EXPECT_EQ(error::kNoError, parser->ProcessAllCommands()); 155 EXPECT_EQ(error::kNoError, parser->ProcessAllCommands());
168 EXPECT_EQ(put, parser->get()); 156 EXPECT_EQ(put, parser->get());
169 Mock::VerifyAndClearExpectations(api_mock()); 157 Mock::VerifyAndClearExpectations(api_mock());
170 } 158 }
171 159
172 // Tests that the parser will wrap correctly at the end of the buffer. 160 // Tests that the parser will wrap correctly at the end of the buffer.
173 TEST_F(CommandParserTest, TestWrap) { 161 TEST_F(CommandParserTest, TestWrap) {
174 scoped_ptr<CommandParser> parser(MakeParser(5)); 162 scoped_ptr<CommandParser> parser(MakeParser(5));
175 CommandBufferOffset put = parser->put(); 163 CommandBufferOffset put = parser->put();
176 CommandHeader header; 164 CommandHeader header;
177 165
178 // add 3 commands with no args (1 word each) 166 // add 3 commands with no args (1 word each)
179 for (unsigned int i = 0; i < 3; ++i) { 167 for (unsigned int i = 0; i < 3; ++i) {
180 header.size = 1; 168 header.size = 1;
181 header.command = i; 169 header.command = i;
182 buffer()[put++].value_header = header; 170 buffer()[put++].value_header = header;
183 AddDoCommandExpect(error::kNoError, i, 0, NULL);
184 } 171 }
185 parser->set_put(put); 172 parser->set_put(put);
186 EXPECT_EQ(put, parser->put()); 173 EXPECT_EQ(put, parser->put());
187 EXPECT_EQ(error::kNoError, parser->ProcessAllCommands()); 174
175 // Process up to 10 commands. 3 entries remaining to put.
176 AddDoCommandsExpect(error::kNoError, 10, 3, 3);
177 EXPECT_EQ(error::kNoError, parser->ProcessCommands(10));
188 EXPECT_EQ(put, parser->get()); 178 EXPECT_EQ(put, parser->get());
189 Mock::VerifyAndClearExpectations(api_mock()); 179 Mock::VerifyAndClearExpectations(api_mock());
190 180
191 // add 1 command with 1 arg (2 words). That should put us at the end of the 181 // add 1 command with 1 arg (2 words). That should put us at the end of the
192 // buffer. 182 // buffer.
193 header.size = 2; 183 header.size = 2;
194 header.command = 3; 184 header.command = 3;
195 buffer()[put++].value_header = header; 185 buffer()[put++].value_header = header;
196 buffer()[put++].value_int32 = 5; 186 buffer()[put++].value_int32 = 5;
197 CommandBufferEntry param;
198 param.value_int32 = 5;
199 AddDoCommandExpect(error::kNoError, 3, 1, &param);
200 187
201 DCHECK_EQ(5, put); 188 DCHECK_EQ(5, put);
202 put = 0; 189 put = 0;
203 parser->set_put(put);
204 EXPECT_EQ(put, parser->put());
205 EXPECT_EQ(error::kNoError, parser->ProcessAllCommands());
206 EXPECT_EQ(put, parser->get());
207 Mock::VerifyAndClearExpectations(api_mock());
208 190
209 // add 1 command with 1 arg (2 words). 191 // add 1 command with 1 arg (2 words).
210 header.size = 2; 192 header.size = 2;
211 header.command = 4; 193 header.command = 4;
212 buffer()[put++].value_header = header; 194 buffer()[put++].value_header = header;
213 buffer()[put++].value_int32 = 6; 195 buffer()[put++].value_int32 = 6;
214 param.value_int32 = 6; 196
215 AddDoCommandExpect(error::kNoError, 4, 1, &param); 197 // 2 entries remaining to end of buffer.
198 AddDoCommandsExpect(
199 error::kNoError, CommandParser::kParseCommandsSlice, 2, 2);
200 // 2 entries remaining to put.
201 AddDoCommandsExpect(
202 error::kNoError, CommandParser::kParseCommandsSlice, 2, 2);
216 parser->set_put(put); 203 parser->set_put(put);
217 EXPECT_EQ(put, parser->put()); 204 EXPECT_EQ(put, parser->put());
205
218 EXPECT_EQ(error::kNoError, parser->ProcessAllCommands()); 206 EXPECT_EQ(error::kNoError, parser->ProcessAllCommands());
219 EXPECT_EQ(put, parser->get()); 207 EXPECT_EQ(put, parser->get());
220 Mock::VerifyAndClearExpectations(api_mock()); 208 Mock::VerifyAndClearExpectations(api_mock());
221 } 209 }
222 210
223 // Tests error conditions. 211 // Tests error conditions.
224 TEST_F(CommandParserTest, TestError) { 212 TEST_F(CommandParserTest, TestError) {
225 const unsigned int kNumEntries = 5; 213 const unsigned int kNumEntries = 5;
226 scoped_ptr<CommandParser> parser(MakeParser(kNumEntries)); 214 scoped_ptr<CommandParser> parser(MakeParser(kNumEntries));
227 CommandBufferOffset put = parser->put(); 215 CommandBufferOffset put = parser->put();
228 CommandHeader header; 216 CommandHeader header;
229 217
230 EXPECT_FALSE(parser->set_get(-1)); 218 EXPECT_FALSE(parser->set_get(-1));
231 EXPECT_FALSE(parser->set_get(kNumEntries)); 219 EXPECT_FALSE(parser->set_get(kNumEntries));
232 220
233 // Generate a command with size 0. 221 // Generate a command with size 0.
234 header.size = 0; 222 header.size = 0;
235 header.command = 3; 223 header.command = 3;
236 buffer()[put++].value_header = header; 224 buffer()[put++].value_header = header;
237 225
238 parser->set_put(put); 226 parser->set_put(put);
239 EXPECT_EQ(put, parser->put()); 227 EXPECT_EQ(put, parser->put());
228
229 AddDoCommandsExpect(
230 error::kInvalidSize, CommandParser::kParseCommandsSlice, 1, 0);
240 EXPECT_EQ(error::kInvalidSize, 231 EXPECT_EQ(error::kInvalidSize,
241 parser->ProcessAllCommands()); 232 parser->ProcessAllCommands());
242 // check that no DoCommand call was made. 233 // check that no DoCommand call was made.
243 Mock::VerifyAndClearExpectations(api_mock()); 234 Mock::VerifyAndClearExpectations(api_mock());
244 235
245 parser.reset(MakeParser(5)); 236 parser.reset(MakeParser(5));
246 put = parser->put(); 237 put = parser->put();
247 238
248 // Generate a command with size 6, extends beyond the end of the buffer. 239 // Generate a command with size 6, extends beyond the end of the buffer.
249 header.size = 6; 240 header.size = 6;
250 header.command = 3; 241 header.command = 3;
251 buffer()[put++].value_header = header; 242 buffer()[put++].value_header = header;
252 243
253 parser->set_put(put); 244 parser->set_put(put);
254 EXPECT_EQ(put, parser->put()); 245 EXPECT_EQ(put, parser->put());
246
247 AddDoCommandsExpect(
248 error::kOutOfBounds, CommandParser::kParseCommandsSlice, 1, 0);
255 EXPECT_EQ(error::kOutOfBounds, 249 EXPECT_EQ(error::kOutOfBounds,
256 parser->ProcessAllCommands()); 250 parser->ProcessAllCommands());
257 // check that no DoCommand call was made. 251 // check that no DoCommand call was made.
258 Mock::VerifyAndClearExpectations(api_mock()); 252 Mock::VerifyAndClearExpectations(api_mock());
259 253
260 parser.reset(MakeParser(5)); 254 parser.reset(MakeParser(5));
261 put = parser->put(); 255 put = parser->put();
262 256
263 // Generates 2 commands. 257 // Generates 2 commands.
264 header.size = 1; 258 header.size = 1;
265 header.command = 3; 259 header.command = 3;
266 buffer()[put++].value_header = header; 260 buffer()[put++].value_header = header;
267 CommandBufferOffset put_post_fail = put; 261 CommandBufferOffset put_post_fail = put;
268 header.size = 1; 262 header.size = 1;
269 header.command = 4; 263 header.command = 4;
270 buffer()[put++].value_header = header; 264 buffer()[put++].value_header = header;
271 265
272 parser->set_put(put); 266 parser->set_put(put);
273 EXPECT_EQ(put, parser->put()); 267 EXPECT_EQ(put, parser->put());
274 // have the first command fail to parse. 268 // have the first command fail to parse.
275 AddDoCommandExpect(error::kUnknownCommand, 3, 0, NULL); 269 AddDoCommandsExpect(
270 error::kUnknownCommand, CommandParser::kParseCommandsSlice, 2, 1);
276 EXPECT_EQ(error::kUnknownCommand, 271 EXPECT_EQ(error::kUnknownCommand,
277 parser->ProcessAllCommands()); 272 parser->ProcessAllCommands());
278 // check that only one command was executed, and that get reflects that 273 // check that only one command was executed, and that get reflects that
279 // correctly. 274 // correctly.
280 EXPECT_EQ(put_post_fail, parser->get()); 275 EXPECT_EQ(put_post_fail, parser->get());
281 Mock::VerifyAndClearExpectations(api_mock()); 276 Mock::VerifyAndClearExpectations(api_mock());
282 // make the second one succeed, and check that the parser recovered fine. 277 // make the second one succeed, and check that the parser recovered fine.
283 AddDoCommandExpect(error::kNoError, 4, 0, NULL); 278 AddDoCommandsExpect(
279 error::kNoError, CommandParser::kParseCommandsSlice, 1, 1);
284 EXPECT_EQ(error::kNoError, parser->ProcessAllCommands()); 280 EXPECT_EQ(error::kNoError, parser->ProcessAllCommands());
285 EXPECT_EQ(put, parser->get()); 281 EXPECT_EQ(put, parser->get());
286 Mock::VerifyAndClearExpectations(api_mock()); 282 Mock::VerifyAndClearExpectations(api_mock());
287 } 283 }
288 284
289 TEST_F(CommandParserTest, SetBuffer) { 285 TEST_F(CommandParserTest, SetBuffer) {
290 scoped_ptr<CommandParser> parser(MakeParser(3)); 286 scoped_ptr<CommandParser> parser(MakeParser(3));
291 CommandBufferOffset put = parser->put(); 287 CommandBufferOffset put = parser->put();
292 CommandHeader header; 288 CommandHeader header;
293 289
294 // add a single command, no args 290 // add a single command, no args
295 header.size = 2; 291 header.size = 2;
296 header.command = 123; 292 header.command = 123;
297 buffer()[put++].value_header = header; 293 buffer()[put++].value_header = header;
298 buffer()[put++].value_int32 = 456; 294 buffer()[put++].value_int32 = 456;
295 parser->set_put(put);
299 296
300 CommandBufferEntry param_array[1]; 297 AddDoCommandsExpect(
301 param_array[0].value_int32 = 456; 298 error::kNoError, CommandParser::kParseCommandsSlice, 2, 2);
302
303 parser->set_put(put);
304 AddDoCommandExpect(error::kNoError, 123, 1, param_array);
305 EXPECT_EQ(error::kNoError, parser->ProcessAllCommands()); 299 EXPECT_EQ(error::kNoError, parser->ProcessAllCommands());
306 // We should have advanced 2 entries 300 // We should have advanced 2 entries
307 EXPECT_EQ(2, parser->get()); 301 EXPECT_EQ(2, parser->get());
308 Mock::VerifyAndClearExpectations(api_mock()); 302 Mock::VerifyAndClearExpectations(api_mock());
309 303
310 scoped_ptr<CommandBufferEntry[]> buffer2(new CommandBufferEntry[2]); 304 scoped_ptr<CommandBufferEntry[]> buffer2(new CommandBufferEntry[2]);
311 parser->SetBuffer( 305 parser->SetBuffer(
312 buffer2.get(), sizeof(CommandBufferEntry) * 2, 0, 306 buffer2.get(), sizeof(CommandBufferEntry) * 2, 0,
313 sizeof(CommandBufferEntry) * 2); 307 sizeof(CommandBufferEntry) * 2);
314 // The put and get should have reset to 0. 308 // The put and get should have reset to 0.
315 EXPECT_EQ(0, parser->get()); 309 EXPECT_EQ(0, parser->get());
316 EXPECT_EQ(0, parser->put()); 310 EXPECT_EQ(0, parser->put());
317 } 311 }
318 312
319 } // namespace gpu 313 } // namespace gpu
OLDNEW
« no previous file with comments | « gpu/command_buffer/service/cmd_parser.cc ('k') | gpu/command_buffer/service/common_decoder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698