OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 #include "gpu/command_buffer/service/buffer_manager.h" | 5 #include "gpu/command_buffer/service/buffer_manager.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <limits> | 9 #include <limits> |
10 | 10 |
(...skipping 16 matching lines...) Expand all Loading... |
27 | 27 |
28 BufferManager::BufferManager(MemoryTracker* memory_tracker, | 28 BufferManager::BufferManager(MemoryTracker* memory_tracker, |
29 FeatureInfo* feature_info) | 29 FeatureInfo* feature_info) |
30 : memory_type_tracker_( | 30 : memory_type_tracker_( |
31 new MemoryTypeTracker(memory_tracker)), | 31 new MemoryTypeTracker(memory_tracker)), |
32 memory_tracker_(memory_tracker), | 32 memory_tracker_(memory_tracker), |
33 feature_info_(feature_info), | 33 feature_info_(feature_info), |
34 allow_buffers_on_multiple_targets_(false), | 34 allow_buffers_on_multiple_targets_(false), |
35 allow_fixed_attribs_(false), | 35 allow_fixed_attribs_(false), |
36 buffer_count_(0), | 36 buffer_count_(0), |
| 37 primitive_restart_enabled_(false), |
37 have_context_(true), | 38 have_context_(true), |
38 use_client_side_arrays_for_stream_buffers_( | 39 use_client_side_arrays_for_stream_buffers_( |
39 feature_info | 40 feature_info |
40 ? feature_info->workarounds() | 41 ? feature_info->workarounds() |
41 .use_client_side_arrays_for_stream_buffers | 42 .use_client_side_arrays_for_stream_buffers |
42 : 0) { | 43 : 0) { |
43 // When created from InProcessCommandBuffer, we won't have a |memory_tracker_| | 44 // When created from InProcessCommandBuffer, we won't have a |memory_tracker_| |
44 // so don't register a dump provider. | 45 // so don't register a dump provider. |
45 if (memory_tracker_) { | 46 if (memory_tracker_) { |
46 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( | 47 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 return NULL; | 193 return NULL; |
193 } | 194 } |
194 return shadow_.get() + offset; | 195 return shadow_.get() + offset; |
195 } | 196 } |
196 | 197 |
197 void Buffer::ClearCache() { | 198 void Buffer::ClearCache() { |
198 range_set_.clear(); | 199 range_set_.clear(); |
199 } | 200 } |
200 | 201 |
201 template <typename T> | 202 template <typename T> |
202 GLuint GetMaxValue(const void* data, GLuint offset, GLsizei count) { | 203 GLuint GetMaxValue(const void* data, GLuint offset, GLsizei count, |
| 204 GLuint primitive_restart_index) { |
203 GLuint max_value = 0; | 205 GLuint max_value = 0; |
204 const T* element = | 206 const T* element = |
205 reinterpret_cast<const T*>(static_cast<const int8_t*>(data) + offset); | 207 reinterpret_cast<const T*>(static_cast<const int8_t*>(data) + offset); |
206 const T* end = element + count; | 208 const T* end = element + count; |
207 for (; element < end; ++element) { | 209 for (; element < end; ++element) { |
208 if (*element > max_value) { | 210 if (*element > max_value) { |
| 211 if (*element == primitive_restart_index) { |
| 212 continue; |
| 213 } |
209 max_value = *element; | 214 max_value = *element; |
210 } | 215 } |
211 } | 216 } |
212 return max_value; | 217 return max_value; |
213 } | 218 } |
214 | 219 |
215 bool Buffer::GetMaxValueForRange( | 220 bool Buffer::GetMaxValueForRange( |
216 GLuint offset, GLsizei count, GLenum type, GLuint* max_value) { | 221 GLuint offset, GLsizei count, GLenum type, GLuint* max_value) { |
217 Range range(offset, count, type); | 222 Range range(offset, count, type); |
218 RangeToMaxValueMap::iterator it = range_set_.find(range); | 223 RangeToMaxValueMap::iterator it = range_set_.find(range); |
219 if (it != range_set_.end()) { | 224 if (it != range_set_.end()) { |
220 *max_value = it->second; | 225 if (it->second.max_value_ == it->second.max_value_pr_enabled_ || |
221 return true; | 226 (!manager_->primitive_restart_enabled_ && it->second.max_value_)) { |
| 227 *max_value = it->second.max_value_; |
| 228 return true; |
| 229 } |
| 230 if (!manager_->primitive_restart_enabled_ && |
| 231 it->second.max_value_pr_enabled_) { |
| 232 *max_value = it->second.max_value_pr_enabled_; |
| 233 return true; |
| 234 } |
222 } | 235 } |
223 | 236 |
224 uint32_t size; | 237 uint32_t size; |
225 if (!SafeMultiplyUint32( | 238 if (!SafeMultiplyUint32( |
226 count, GLES2Util::GetGLTypeSizeForBuffers(type), &size)) { | 239 count, GLES2Util::GetGLTypeSizeForBuffers(type), &size)) { |
227 return false; | 240 return false; |
228 } | 241 } |
229 | 242 |
230 if (!SafeAddUint32(offset, size, &size)) { | 243 if (!SafeAddUint32(offset, size, &size)) { |
231 return false; | 244 return false; |
232 } | 245 } |
233 | 246 |
234 if (size > static_cast<uint32_t>(size_)) { | 247 if (size > static_cast<uint32_t>(size_)) { |
235 return false; | 248 return false; |
236 } | 249 } |
237 | 250 |
238 if (!shadowed_) { | 251 if (!shadowed_) { |
239 return false; | 252 return false; |
240 } | 253 } |
241 | 254 |
242 // Scan the range for the max value and store | 255 // Scan the range for the max value and store |
| 256 bool index_buffer = |
| 257 this->initial_target() == GL_ELEMENT_ARRAY_BUFFER ? true : false; |
| 258 GLuint primitive_restart_index = 0; |
| 259 |
243 GLuint max_v = 0; | 260 GLuint max_v = 0; |
244 switch (type) { | 261 switch (type) { |
245 case GL_UNSIGNED_BYTE: | 262 case GL_UNSIGNED_BYTE: |
246 max_v = GetMaxValue<uint8_t>(shadow_.get(), offset, count); | 263 if (index_buffer && manager_->primitive_restart_enabled_) { |
| 264 primitive_restart_index = 0xFF; |
| 265 } |
| 266 max_v = GetMaxValue<uint8_t>(shadow_.get(), offset, count, |
| 267 primitive_restart_index); |
247 break; | 268 break; |
248 case GL_UNSIGNED_SHORT: | 269 case GL_UNSIGNED_SHORT: |
249 // Check we are not accessing an odd byte for a 2 byte value. | 270 // Check we are not accessing an odd byte for a 2 byte value. |
250 if ((offset & 1) != 0) { | 271 if ((offset & 1) != 0) { |
251 return false; | 272 return false; |
252 } | 273 } |
253 max_v = GetMaxValue<uint16_t>(shadow_.get(), offset, count); | 274 if (index_buffer && manager_->primitive_restart_enabled_) { |
| 275 primitive_restart_index = 0xFFFF; |
| 276 } |
| 277 max_v = GetMaxValue<uint16_t>(shadow_.get(), offset, count, |
| 278 primitive_restart_index); |
254 break; | 279 break; |
255 case GL_UNSIGNED_INT: | 280 case GL_UNSIGNED_INT: |
256 // Check we are not accessing a non aligned address for a 4 byte value. | 281 // Check we are not accessing a non aligned address for a 4 byte value. |
257 if ((offset & 3) != 0) { | 282 if ((offset & 3) != 0) { |
258 return false; | 283 return false; |
259 } | 284 } |
260 max_v = GetMaxValue<uint32_t>(shadow_.get(), offset, count); | 285 if (index_buffer && manager_->primitive_restart_enabled_) { |
| 286 primitive_restart_index = 0xFFFFFFFF; |
| 287 } |
| 288 max_v = GetMaxValue<uint32_t>(shadow_.get(), offset, count, |
| 289 primitive_restart_index); |
261 break; | 290 break; |
262 default: | 291 default: |
263 NOTREACHED(); // should never get here by validation. | 292 NOTREACHED(); // should never get here by validation. |
264 break; | 293 break; |
265 } | 294 } |
266 range_set_.insert(std::make_pair(range, max_v)); | 295 |
| 296 if (it != range_set_.end()) { |
| 297 if (manager_->primitive_restart_enabled_) { |
| 298 it->second.max_value_ = max_v; |
| 299 } else { |
| 300 it->second.max_value_pr_enabled_ = max_v; |
| 301 } |
| 302 } else { |
| 303 GLuint temp_max_value = 0, temp_max_value_pr_enabled = 0; |
| 304 if (!index_buffer) { |
| 305 temp_max_value = max_v; |
| 306 temp_max_value_pr_enabled = max_v; |
| 307 } else { |
| 308 if (manager_->primitive_restart_enabled_) { |
| 309 temp_max_value_pr_enabled = max_v; |
| 310 } else { |
| 311 temp_max_value = max_v; |
| 312 } |
| 313 } |
| 314 struct MaxValue value(temp_max_value, temp_max_value_pr_enabled); |
| 315 range_set_.insert(std::make_pair(range, value)); |
| 316 } |
267 *max_value = max_v; | 317 *max_value = max_v; |
268 return true; | 318 return true; |
269 } | 319 } |
270 | 320 |
271 bool BufferManager::GetClientId(GLuint service_id, GLuint* client_id) const { | 321 bool BufferManager::GetClientId(GLuint service_id, GLuint* client_id) const { |
272 // This doesn't need to be fast. It's only used during slow queries. | 322 // This doesn't need to be fast. It's only used during slow queries. |
273 for (BufferMap::const_iterator it = buffers_.begin(); | 323 for (BufferMap::const_iterator it = buffers_.begin(); |
274 it != buffers_.end(); ++it) { | 324 it != buffers_.end(); ++it) { |
275 if (it->second->service_id() == service_id) { | 325 if (it->second->service_id() == service_id) { |
276 *client_id = it->first; | 326 *client_id = it->first; |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
529 case GL_TRANSFORM_FEEDBACK_BUFFER: | 579 case GL_TRANSFORM_FEEDBACK_BUFFER: |
530 return state->bound_transform_feedback_buffer.get(); | 580 return state->bound_transform_feedback_buffer.get(); |
531 case GL_UNIFORM_BUFFER: | 581 case GL_UNIFORM_BUFFER: |
532 return state->bound_uniform_buffer.get(); | 582 return state->bound_uniform_buffer.get(); |
533 default: | 583 default: |
534 NOTREACHED(); | 584 NOTREACHED(); |
535 return nullptr; | 585 return nullptr; |
536 } | 586 } |
537 } | 587 } |
538 | 588 |
| 589 void BufferManager::SetPrimitiveRestartState(bool enabled) { |
| 590 if (primitive_restart_enabled_ != enabled) { |
| 591 primitive_restart_enabled_ = enabled; |
| 592 } |
| 593 } |
| 594 |
539 bool BufferManager::OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, | 595 bool BufferManager::OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, |
540 base::trace_event::ProcessMemoryDump* pmd) { | 596 base::trace_event::ProcessMemoryDump* pmd) { |
541 const int client_id = memory_tracker_->ClientId(); | 597 const int client_id = memory_tracker_->ClientId(); |
542 for (const auto& buffer_entry : buffers_) { | 598 for (const auto& buffer_entry : buffers_) { |
543 const auto& client_buffer_id = buffer_entry.first; | 599 const auto& client_buffer_id = buffer_entry.first; |
544 const auto& buffer = buffer_entry.second; | 600 const auto& buffer = buffer_entry.second; |
545 | 601 |
546 std::string dump_name = base::StringPrintf( | 602 std::string dump_name = base::StringPrintf( |
547 "gpu/gl/buffers/client_%d/buffer_%d", client_id, client_buffer_id); | 603 "gpu/gl/buffers/client_%d/buffer_%d", client_id, client_buffer_id); |
548 base::trace_event::MemoryAllocatorDump* dump = | 604 base::trace_event::MemoryAllocatorDump* dump = |
549 pmd->CreateAllocatorDump(dump_name); | 605 pmd->CreateAllocatorDump(dump_name); |
550 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, | 606 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, |
551 base::trace_event::MemoryAllocatorDump::kUnitsBytes, | 607 base::trace_event::MemoryAllocatorDump::kUnitsBytes, |
552 static_cast<uint64_t>(buffer->size())); | 608 static_cast<uint64_t>(buffer->size())); |
553 | 609 |
554 auto guid = gfx::GetGLBufferGUIDForTracing( | 610 auto guid = gfx::GetGLBufferGUIDForTracing( |
555 memory_tracker_->ShareGroupTracingGUID(), client_buffer_id); | 611 memory_tracker_->ShareGroupTracingGUID(), client_buffer_id); |
556 pmd->CreateSharedGlobalAllocatorDump(guid); | 612 pmd->CreateSharedGlobalAllocatorDump(guid); |
557 pmd->AddOwnershipEdge(dump->guid(), guid); | 613 pmd->AddOwnershipEdge(dump->guid(), guid); |
558 } | 614 } |
559 return true; | 615 return true; |
560 } | 616 } |
561 | 617 |
562 } // namespace gles2 | 618 } // namespace gles2 |
563 } // namespace gpu | 619 } // namespace gpu |
OLD | NEW |