| OLD | NEW |
| 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2015 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 "ui/gl/gpu_timing.h" | 5 #include "ui/gl/gpu_timing.h" |
| 6 | 6 |
| 7 #include "base/macros.h" |
| 7 #include "base/time/time.h" | 8 #include "base/time/time.h" |
| 8 #include "ui/gl/gl_bindings.h" | 9 #include "ui/gl/gl_bindings.h" |
| 9 #include "ui/gl/gl_context.h" | 10 #include "ui/gl/gl_context.h" |
| 10 #include "ui/gl/gl_version_info.h" | 11 #include "ui/gl/gl_version_info.h" |
| 11 | 12 |
| 12 namespace gfx { | 13 namespace gfx { |
| 13 | 14 |
| 14 class TimeElapsedTimerQuery; | 15 class TimeElapsedTimerQuery; |
| 15 class TimerQuery; | 16 class TimerQuery; |
| 16 | 17 |
| 17 int64_t NanoToMicro(uint64_t nano_seconds) { | 18 int64_t NanoToMicro(uint64_t nano_seconds) { |
| 18 const uint64_t up = nano_seconds + base::Time::kNanosecondsPerMicrosecond / 2; | 19 const uint64_t up = nano_seconds + base::Time::kNanosecondsPerMicrosecond / 2; |
| 19 return static_cast<int64_t>(up / base::Time::kNanosecondsPerMicrosecond); | 20 return static_cast<int64_t>(up / base::Time::kNanosecondsPerMicrosecond); |
| 20 } | 21 } |
| 21 | 22 |
| 22 class GPUTimingImpl : public GPUTiming { | 23 class GPUTimingImpl : public GPUTiming { |
| 23 public: | 24 public: |
| 24 GPUTimingImpl(GLContextReal* context); | 25 GPUTimingImpl(GLContextReal* context); |
| 25 ~GPUTimingImpl() override; | 26 ~GPUTimingImpl() override; |
| 26 | 27 |
| 27 void ForceTimeElapsedQuery() { force_time_elapsed_query_ = true; } | 28 void ForceTimeElapsedQuery() { force_time_elapsed_query_ = true; } |
| 28 bool IsForceTimeElapsedQuery() { return force_time_elapsed_query_; } | 29 bool IsForceTimeElapsedQuery() { return force_time_elapsed_query_; } |
| 29 | 30 |
| 30 GPUTiming::TimerType GetTimerType() const { return timer_type_; } | 31 GPUTiming::TimerType GetTimerType() const { return timer_type_; } |
| 31 | 32 |
| 32 uint32_t GetDisjointCount(); | 33 uint32_t GetDisjointCount(); |
| 33 int64 CalculateTimerOffset(); | 34 int64_t CalculateTimerOffset(); |
| 34 | 35 |
| 35 scoped_refptr<QueryResult> BeginElapsedTimeQuery(); | 36 scoped_refptr<QueryResult> BeginElapsedTimeQuery(); |
| 36 void EndElapsedTimeQuery(scoped_refptr<QueryResult> result); | 37 void EndElapsedTimeQuery(scoped_refptr<QueryResult> result); |
| 37 | 38 |
| 38 scoped_refptr<QueryResult> DoTimeStampQuery(); | 39 scoped_refptr<QueryResult> DoTimeStampQuery(); |
| 39 | 40 |
| 40 int64 GetCurrentCPUTime() { | 41 int64_t GetCurrentCPUTime() { |
| 41 return cpu_time_for_testing_.is_null() | 42 return cpu_time_for_testing_.is_null() |
| 42 ? (base::TimeTicks::Now() - base::TimeTicks()).InMicroseconds() | 43 ? (base::TimeTicks::Now() - base::TimeTicks()).InMicroseconds() |
| 43 : cpu_time_for_testing_.Run(); | 44 : cpu_time_for_testing_.Run(); |
| 44 } | 45 } |
| 45 void SetCpuTimeForTesting(const base::Callback<int64(void)>& cpu_time) { | 46 void SetCpuTimeForTesting(const base::Callback<int64_t(void)>& cpu_time) { |
| 46 cpu_time_for_testing_ = cpu_time; | 47 cpu_time_for_testing_ = cpu_time; |
| 47 } | 48 } |
| 48 | 49 |
| 49 void UpdateQueryResults(); | 50 void UpdateQueryResults(); |
| 50 | 51 |
| 51 int64_t GetMaxTimeStamp() { return max_time_stamp_; } | 52 int64_t GetMaxTimeStamp() { return max_time_stamp_; } |
| 52 void UpdateMaxTimeStamp(int64_t value) { | 53 void UpdateMaxTimeStamp(int64_t value) { |
| 53 max_time_stamp_ = std::max(max_time_stamp_, value); | 54 max_time_stamp_ = std::max(max_time_stamp_, value); |
| 54 } | 55 } |
| 55 | 56 |
| 56 uint32_t GetElapsedQueryCount() { return elapsed_query_count_; } | 57 uint32_t GetElapsedQueryCount() { return elapsed_query_count_; } |
| 57 void IncElapsedQueryCount() { elapsed_query_count_++; } | 58 void IncElapsedQueryCount() { elapsed_query_count_++; } |
| 58 void DecElapsedQueryCount() { elapsed_query_count_--; } | 59 void DecElapsedQueryCount() { elapsed_query_count_--; } |
| 59 | 60 |
| 60 void SetLastElapsedQuery(scoped_refptr<TimeElapsedTimerQuery> query); | 61 void SetLastElapsedQuery(scoped_refptr<TimeElapsedTimerQuery> query); |
| 61 scoped_refptr<TimeElapsedTimerQuery> GetLastElapsedQuery(); | 62 scoped_refptr<TimeElapsedTimerQuery> GetLastElapsedQuery(); |
| 62 | 63 |
| 63 void HandleBadQuery(); | 64 void HandleBadQuery(); |
| 64 bool IsGoodQueryID(uint32_t query_id); | 65 bool IsGoodQueryID(uint32_t query_id); |
| 65 | 66 |
| 66 private: | 67 private: |
| 67 scoped_refptr<GPUTimingClient> CreateGPUTimingClient() override; | 68 scoped_refptr<GPUTimingClient> CreateGPUTimingClient() override; |
| 68 | 69 |
| 69 base::Callback<int64(void)> cpu_time_for_testing_; | 70 base::Callback<int64_t(void)> cpu_time_for_testing_; |
| 70 GPUTiming::TimerType timer_type_ = GPUTiming::kTimerTypeInvalid; | 71 GPUTiming::TimerType timer_type_ = GPUTiming::kTimerTypeInvalid; |
| 71 uint32_t disjoint_counter_ = 0; | 72 uint32_t disjoint_counter_ = 0; |
| 72 int64 offset_ = 0; // offset cache when timer_type_ == kTimerTypeARB | 73 int64_t offset_ = 0; // offset cache when timer_type_ == kTimerTypeARB |
| 73 bool offset_valid_ = false; | 74 bool offset_valid_ = false; |
| 74 bool force_time_elapsed_query_ = false; | 75 bool force_time_elapsed_query_ = false; |
| 75 | 76 |
| 76 uint32_t next_timer_query_id_ = 0; | 77 uint32_t next_timer_query_id_ = 0; |
| 77 uint32_t next_good_timer_query_id_ = 0; // identify bad ids for disjoints. | 78 uint32_t next_good_timer_query_id_ = 0; // identify bad ids for disjoints. |
| 78 uint32_t query_disjoint_count_ = 0; | 79 uint32_t query_disjoint_count_ = 0; |
| 79 | 80 |
| 80 // Extra state tracking data for elapsed timer queries. | 81 // Extra state tracking data for elapsed timer queries. |
| 81 int64_t max_time_stamp_ = 0; | 82 int64_t max_time_stamp_ = 0; |
| 82 uint32_t elapsed_query_count_ = 0; | 83 uint32_t elapsed_query_count_ = 0; |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 284 } | 285 } |
| 285 | 286 |
| 286 // Fills out query result start and end, called after IsAvailable() is true. | 287 // Fills out query result start and end, called after IsAvailable() is true. |
| 287 void UpdateQueryResults(GPUTimingImpl* gpu_timing) override { | 288 void UpdateQueryResults(GPUTimingImpl* gpu_timing) override { |
| 288 DCHECK(IsAvailable(gpu_timing)); | 289 DCHECK(IsAvailable(gpu_timing)); |
| 289 | 290 |
| 290 GLuint64 result_value = 0; | 291 GLuint64 result_value = 0; |
| 291 glGetQueryObjectui64v(gl_query_id_, GL_QUERY_RESULT, &result_value); | 292 glGetQueryObjectui64v(gl_query_id_, GL_QUERY_RESULT, &result_value); |
| 292 const int64_t micro_results = NanoToMicro(result_value); | 293 const int64_t micro_results = NanoToMicro(result_value); |
| 293 | 294 |
| 294 const int64 offset = gpu_timing->CalculateTimerOffset(); | 295 const int64_t offset = gpu_timing->CalculateTimerOffset(); |
| 295 const int64_t adjusted_result = micro_results + offset; | 296 const int64_t adjusted_result = micro_results + offset; |
| 296 DCHECK(query_result_.get()); | 297 DCHECK(query_result_.get()); |
| 297 query_result_->SetStartValue(adjusted_result); | 298 query_result_->SetStartValue(adjusted_result); |
| 298 query_result_->SetEndValue(adjusted_result); | 299 query_result_->SetEndValue(adjusted_result); |
| 299 time_stamp_ = adjusted_result; | 300 time_stamp_ = adjusted_result; |
| 300 } | 301 } |
| 301 | 302 |
| 302 private: | 303 private: |
| 303 ~TimeStampTimerQuery() override {} | 304 ~TimeStampTimerQuery() override {} |
| 304 uint32_t gl_query_id_ = 0; | 305 uint32_t gl_query_id_ = 0; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 328 GLint disjoint_value = 0; | 329 GLint disjoint_value = 0; |
| 329 glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value); | 330 glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value); |
| 330 if (disjoint_value) { | 331 if (disjoint_value) { |
| 331 offset_valid_ = false; | 332 offset_valid_ = false; |
| 332 disjoint_counter_++; | 333 disjoint_counter_++; |
| 333 } | 334 } |
| 334 } | 335 } |
| 335 return disjoint_counter_; | 336 return disjoint_counter_; |
| 336 } | 337 } |
| 337 | 338 |
| 338 int64 GPUTimingImpl::CalculateTimerOffset() { | 339 int64_t GPUTimingImpl::CalculateTimerOffset() { |
| 339 if (!offset_valid_) { | 340 if (!offset_valid_) { |
| 340 if (timer_type_ == GPUTiming::kTimerTypeDisjoint || | 341 if (timer_type_ == GPUTiming::kTimerTypeDisjoint || |
| 341 timer_type_ == GPUTiming::kTimerTypeARB) { | 342 timer_type_ == GPUTiming::kTimerTypeARB) { |
| 342 GLint64 gl_now = 0; | 343 GLint64 gl_now = 0; |
| 343 glGetInteger64v(GL_TIMESTAMP, &gl_now); | 344 glGetInteger64v(GL_TIMESTAMP, &gl_now); |
| 344 int64_t micro_now = NanoToMicro(gl_now); | 345 int64_t micro_now = NanoToMicro(gl_now); |
| 345 offset_ = GetCurrentCPUTime() - micro_now; | 346 offset_ = GetCurrentCPUTime() - micro_now; |
| 346 offset_valid_ = (timer_type_ == GPUTiming::kTimerTypeARB); | 347 offset_valid_ = (timer_type_ == GPUTiming::kTimerTypeARB); |
| 347 } else { | 348 } else { |
| 348 offset_ = 0; | 349 offset_ = 0; |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 527 } else { | 528 } else { |
| 528 gpu_timing_client_->gpu_timing_->UpdateQueryResults(); | 529 gpu_timing_client_->gpu_timing_->UpdateQueryResults(); |
| 529 if (result->IsAvailable()) | 530 if (result->IsAvailable()) |
| 530 timer_state_ = kTimerState_ResultAvailable; | 531 timer_state_ = kTimerState_ResultAvailable; |
| 531 } | 532 } |
| 532 } | 533 } |
| 533 | 534 |
| 534 return (timer_state_ == kTimerState_ResultAvailable); | 535 return (timer_state_ == kTimerState_ResultAvailable); |
| 535 } | 536 } |
| 536 | 537 |
| 537 void GPUTimer::GetStartEndTimestamps(int64* start, int64* end) { | 538 void GPUTimer::GetStartEndTimestamps(int64_t* start, int64_t* end) { |
| 538 DCHECK(start && end); | 539 DCHECK(start && end); |
| 539 DCHECK(elapsed_timer_result_.get() || time_stamp_result_.get()); | 540 DCHECK(elapsed_timer_result_.get() || time_stamp_result_.get()); |
| 540 DCHECK(IsAvailable()); | 541 DCHECK(IsAvailable()); |
| 541 const int64_t time_stamp = time_stamp_result_.get() ? | 542 const int64_t time_stamp = time_stamp_result_.get() ? |
| 542 time_stamp_result_->GetStartValue() : | 543 time_stamp_result_->GetStartValue() : |
| 543 elapsed_timer_result_->GetStartValue(); | 544 elapsed_timer_result_->GetStartValue(); |
| 544 const int64_t elapsed_time = elapsed_timer_result_.get() ? | 545 const int64_t elapsed_time = elapsed_timer_result_.get() ? |
| 545 elapsed_timer_result_->GetDelta() : | 546 elapsed_timer_result_->GetDelta() : |
| 546 0; | 547 0; |
| 547 | 548 |
| 548 *start = time_stamp; | 549 *start = time_stamp; |
| 549 *end = time_stamp + elapsed_time; | 550 *end = time_stamp + elapsed_time; |
| 550 } | 551 } |
| 551 | 552 |
| 552 int64 GPUTimer::GetDeltaElapsed() { | 553 int64_t GPUTimer::GetDeltaElapsed() { |
| 553 DCHECK(IsAvailable()); | 554 DCHECK(IsAvailable()); |
| 554 if (elapsed_timer_result_.get()) | 555 if (elapsed_timer_result_.get()) |
| 555 return elapsed_timer_result_->GetDelta(); | 556 return elapsed_timer_result_->GetDelta(); |
| 556 return 0; | 557 return 0; |
| 557 } | 558 } |
| 558 | 559 |
| 559 GPUTimer::GPUTimer(scoped_refptr<GPUTimingClient> gpu_timing_client, | 560 GPUTimer::GPUTimer(scoped_refptr<GPUTimingClient> gpu_timing_client, |
| 560 bool use_elapsed_timer) | 561 bool use_elapsed_timer) |
| 561 : use_elapsed_timer_(use_elapsed_timer), | 562 : use_elapsed_timer_(use_elapsed_timer), |
| 562 gpu_timing_client_(gpu_timing_client) { | 563 gpu_timing_client_(gpu_timing_client) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 599 if (timer_type_ == GPUTiming::kTimerTypeDisjoint) { | 600 if (timer_type_ == GPUTiming::kTimerTypeDisjoint) { |
| 600 DCHECK(gpu_timing_ != nullptr); | 601 DCHECK(gpu_timing_ != nullptr); |
| 601 const uint32_t total_disjoint_count = gpu_timing_->GetDisjointCount(); | 602 const uint32_t total_disjoint_count = gpu_timing_->GetDisjointCount(); |
| 602 const bool disjoint_triggered = total_disjoint_count != disjoint_counter_; | 603 const bool disjoint_triggered = total_disjoint_count != disjoint_counter_; |
| 603 disjoint_counter_ = total_disjoint_count; | 604 disjoint_counter_ = total_disjoint_count; |
| 604 return disjoint_triggered; | 605 return disjoint_triggered; |
| 605 } | 606 } |
| 606 return false; | 607 return false; |
| 607 } | 608 } |
| 608 | 609 |
| 609 int64 GPUTimingClient::GetCurrentCPUTime() { | 610 int64_t GPUTimingClient::GetCurrentCPUTime() { |
| 610 DCHECK(gpu_timing_); | 611 DCHECK(gpu_timing_); |
| 611 return gpu_timing_->GetCurrentCPUTime(); | 612 return gpu_timing_->GetCurrentCPUTime(); |
| 612 } | 613 } |
| 613 | 614 |
| 614 void GPUTimingClient::SetCpuTimeForTesting( | 615 void GPUTimingClient::SetCpuTimeForTesting( |
| 615 const base::Callback<int64(void)>& cpu_time) { | 616 const base::Callback<int64_t(void)>& cpu_time) { |
| 616 DCHECK(gpu_timing_); | 617 DCHECK(gpu_timing_); |
| 617 gpu_timing_->SetCpuTimeForTesting(cpu_time); | 618 gpu_timing_->SetCpuTimeForTesting(cpu_time); |
| 618 } | 619 } |
| 619 | 620 |
| 620 bool GPUTimingClient::IsForceTimeElapsedQuery() { | 621 bool GPUTimingClient::IsForceTimeElapsedQuery() { |
| 621 DCHECK(gpu_timing_); | 622 DCHECK(gpu_timing_); |
| 622 return gpu_timing_->IsForceTimeElapsedQuery(); | 623 return gpu_timing_->IsForceTimeElapsedQuery(); |
| 623 } | 624 } |
| 624 | 625 |
| 625 void GPUTimingClient::ForceTimeElapsedQuery() { | 626 void GPUTimingClient::ForceTimeElapsedQuery() { |
| 626 DCHECK(gpu_timing_); | 627 DCHECK(gpu_timing_); |
| 627 gpu_timing_->ForceTimeElapsedQuery(); | 628 gpu_timing_->ForceTimeElapsedQuery(); |
| 628 } | 629 } |
| 629 | 630 |
| 630 GPUTimingClient::~GPUTimingClient() { | 631 GPUTimingClient::~GPUTimingClient() { |
| 631 } | 632 } |
| 632 | 633 |
| 633 } // namespace gfx | 634 } // namespace gfx |
| OLD | NEW |