Chromium Code Reviews| 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) { |
| 222 bool index_buffer = | |
| 223 this->initial_target() == GL_ELEMENT_ARRAY_BUFFER ? true : false; | |
| 224 GLuint primitive_restart_index = 0; | |
| 225 if (index_buffer && manager_->primitive_restart_enabled_) { | |
| 226 switch (type) { | |
| 227 case GL_UNSIGNED_BYTE: | |
| 228 primitive_restart_index = 0xFF; | |
| 229 break; | |
| 230 case GL_UNSIGNED_SHORT: | |
| 231 primitive_restart_index = 0xFFFF; | |
| 232 break; | |
| 233 case GL_UNSIGNED_INT: | |
| 234 primitive_restart_index = 0xFFFFFFFF; | |
| 235 break; | |
| 236 default: | |
| 237 NOTREACHED(); // should never get here by validation. | |
| 238 break; | |
| 239 } | |
| 240 } | |
| 241 | |
| 217 Range range(offset, count, type); | 242 Range range(offset, count, type); |
|
Ken Russell (switch to Gerrit)
2016/03/16 16:18:07
The suggestion is to add the "primitive restart en
yunchao
2016/03/17 00:19:02
Ken, I tried this method at first. But the first e
Zhenyao Mo
2016/03/18 20:28:44
Yunchao, I think you misunderstood. The suggestio
| |
| 218 RangeToMaxValueMap::iterator it = range_set_.find(range); | 243 RangeToMaxValueMap::iterator it = range_set_.find(range); |
| 219 if (it != range_set_.end()) { | 244 if (it != range_set_.end()) { |
| 220 *max_value = it->second; | 245 if (!index_buffer || !it->second.primitive_restart_flipped_ || |
| 221 return true; | 246 (manager_->primitive_restart_enabled_ && |
| 247 it->second.max_value_ < primitive_restart_index)) { | |
| 248 *max_value = it->second.max_value_; | |
| 249 it->second.primitive_restart_flipped_ = false; | |
| 250 return true; | |
| 251 } | |
| 222 } | 252 } |
| 223 | 253 |
| 224 uint32_t size; | 254 uint32_t size; |
| 225 if (!SafeMultiplyUint32( | 255 if (!SafeMultiplyUint32( |
| 226 count, GLES2Util::GetGLTypeSizeForBuffers(type), &size)) { | 256 count, GLES2Util::GetGLTypeSizeForBuffers(type), &size)) { |
| 227 return false; | 257 return false; |
| 228 } | 258 } |
| 229 | 259 |
| 230 if (!SafeAddUint32(offset, size, &size)) { | 260 if (!SafeAddUint32(offset, size, &size)) { |
| 231 return false; | 261 return false; |
| 232 } | 262 } |
| 233 | 263 |
| 234 if (size > static_cast<uint32_t>(size_)) { | 264 if (size > static_cast<uint32_t>(size_)) { |
| 235 return false; | 265 return false; |
| 236 } | 266 } |
| 237 | 267 |
| 238 if (!shadowed_) { | 268 if (!shadowed_) { |
| 239 return false; | 269 return false; |
| 240 } | 270 } |
| 241 | 271 |
| 242 // Scan the range for the max value and store | 272 // Scan the range for the max value and store |
| 243 GLuint max_v = 0; | 273 GLuint max_v = 0; |
| 244 switch (type) { | 274 switch (type) { |
| 245 case GL_UNSIGNED_BYTE: | 275 case GL_UNSIGNED_BYTE: |
| 246 max_v = GetMaxValue<uint8_t>(shadow_.get(), offset, count); | 276 max_v = GetMaxValue<uint8_t>(shadow_.get(), offset, count, |
| 277 primitive_restart_index); | |
| 247 break; | 278 break; |
| 248 case GL_UNSIGNED_SHORT: | 279 case GL_UNSIGNED_SHORT: |
| 249 // Check we are not accessing an odd byte for a 2 byte value. | 280 // Check we are not accessing an odd byte for a 2 byte value. |
| 250 if ((offset & 1) != 0) { | 281 if ((offset & 1) != 0) { |
| 251 return false; | 282 return false; |
| 252 } | 283 } |
| 253 max_v = GetMaxValue<uint16_t>(shadow_.get(), offset, count); | 284 max_v = GetMaxValue<uint16_t>(shadow_.get(), offset, count, |
| 285 primitive_restart_index); | |
| 254 break; | 286 break; |
| 255 case GL_UNSIGNED_INT: | 287 case GL_UNSIGNED_INT: |
| 256 // Check we are not accessing a non aligned address for a 4 byte value. | 288 // Check we are not accessing a non aligned address for a 4 byte value. |
| 257 if ((offset & 3) != 0) { | 289 if ((offset & 3) != 0) { |
| 258 return false; | 290 return false; |
| 259 } | 291 } |
| 260 max_v = GetMaxValue<uint32_t>(shadow_.get(), offset, count); | 292 max_v = GetMaxValue<uint32_t>(shadow_.get(), offset, count, |
| 293 primitive_restart_index); | |
| 261 break; | 294 break; |
| 262 default: | 295 default: |
| 263 NOTREACHED(); // should never get here by validation. | 296 NOTREACHED(); // should never get here by validation. |
| 264 break; | 297 break; |
| 265 } | 298 } |
| 266 range_set_.insert(std::make_pair(range, max_v)); | 299 if (it != range_set_.end()) { |
| 300 it->second.max_value_ = max_v; | |
| 301 it->second.primitive_restart_flipped_ = false; | |
| 302 } else { | |
| 303 struct MaxValue value(max_v); | |
| 304 range_set_.insert(std::make_pair(range, value)); | |
| 305 } | |
| 267 *max_value = max_v; | 306 *max_value = max_v; |
| 268 return true; | 307 return true; |
| 269 } | 308 } |
| 270 | 309 |
| 271 bool BufferManager::GetClientId(GLuint service_id, GLuint* client_id) const { | 310 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. | 311 // This doesn't need to be fast. It's only used during slow queries. |
| 273 for (BufferMap::const_iterator it = buffers_.begin(); | 312 for (BufferMap::const_iterator it = buffers_.begin(); |
| 274 it != buffers_.end(); ++it) { | 313 it != buffers_.end(); ++it) { |
| 275 if (it->second->service_id() == service_id) { | 314 if (it->second->service_id() == service_id) { |
| 276 *client_id = it->first; | 315 *client_id = it->first; |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 529 case GL_TRANSFORM_FEEDBACK_BUFFER: | 568 case GL_TRANSFORM_FEEDBACK_BUFFER: |
| 530 return state->bound_transform_feedback_buffer.get(); | 569 return state->bound_transform_feedback_buffer.get(); |
| 531 case GL_UNIFORM_BUFFER: | 570 case GL_UNIFORM_BUFFER: |
| 532 return state->bound_uniform_buffer.get(); | 571 return state->bound_uniform_buffer.get(); |
| 533 default: | 572 default: |
| 534 NOTREACHED(); | 573 NOTREACHED(); |
| 535 return nullptr; | 574 return nullptr; |
| 536 } | 575 } |
| 537 } | 576 } |
| 538 | 577 |
| 578 void BufferManager::SetPrimitiveRestartState(bool enabled) { | |
| 579 if (primitive_restart_enabled_ != enabled) { | |
| 580 primitive_restart_enabled_ = enabled; | |
| 581 | |
| 582 for (BufferMap::const_iterator it = buffers_.begin(); | |
| 583 it != buffers_.end(); ++it) { | |
| 584 if (it->second->initial_target() == GL_ELEMENT_ARRAY_BUFFER) { | |
| 585 Buffer::RangeToMaxValueMap::iterator range_set_it; | |
| 586 for (range_set_it = it->second->range_set_.begin(); | |
| 587 range_set_it != it->second->range_set_.end(); ++range_set_it) { | |
| 588 range_set_it->second.primitive_restart_flipped_ = | |
| 589 !range_set_it->second.primitive_restart_flipped_; | |
| 590 } | |
| 591 } | |
| 592 } | |
| 593 } | |
| 594 } | |
| 595 | |
| 539 bool BufferManager::OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, | 596 bool BufferManager::OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, |
| 540 base::trace_event::ProcessMemoryDump* pmd) { | 597 base::trace_event::ProcessMemoryDump* pmd) { |
| 541 const int client_id = memory_tracker_->ClientId(); | 598 const int client_id = memory_tracker_->ClientId(); |
| 542 for (const auto& buffer_entry : buffers_) { | 599 for (const auto& buffer_entry : buffers_) { |
| 543 const auto& client_buffer_id = buffer_entry.first; | 600 const auto& client_buffer_id = buffer_entry.first; |
| 544 const auto& buffer = buffer_entry.second; | 601 const auto& buffer = buffer_entry.second; |
| 545 | 602 |
| 546 std::string dump_name = base::StringPrintf( | 603 std::string dump_name = base::StringPrintf( |
| 547 "gpu/gl/buffers/client_%d/buffer_%d", client_id, client_buffer_id); | 604 "gpu/gl/buffers/client_%d/buffer_%d", client_id, client_buffer_id); |
| 548 base::trace_event::MemoryAllocatorDump* dump = | 605 base::trace_event::MemoryAllocatorDump* dump = |
| 549 pmd->CreateAllocatorDump(dump_name); | 606 pmd->CreateAllocatorDump(dump_name); |
| 550 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, | 607 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, |
| 551 base::trace_event::MemoryAllocatorDump::kUnitsBytes, | 608 base::trace_event::MemoryAllocatorDump::kUnitsBytes, |
| 552 static_cast<uint64_t>(buffer->size())); | 609 static_cast<uint64_t>(buffer->size())); |
| 553 | 610 |
| 554 auto guid = gfx::GetGLBufferGUIDForTracing( | 611 auto guid = gfx::GetGLBufferGUIDForTracing( |
| 555 memory_tracker_->ShareGroupTracingGUID(), client_buffer_id); | 612 memory_tracker_->ShareGroupTracingGUID(), client_buffer_id); |
| 556 pmd->CreateSharedGlobalAllocatorDump(guid); | 613 pmd->CreateSharedGlobalAllocatorDump(guid); |
| 557 pmd->AddOwnershipEdge(dump->guid(), guid); | 614 pmd->AddOwnershipEdge(dump->guid(), guid); |
| 558 } | 615 } |
| 559 return true; | 616 return true; |
| 560 } | 617 } |
| 561 | 618 |
| 562 } // namespace gles2 | 619 } // namespace gles2 |
| 563 } // namespace gpu | 620 } // namespace gpu |
| OLD | NEW |