15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file contains the implementation of the command buffer helper class. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "gpu/command_buffer/client/cmd_buffer_helper.h" 8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/logging.h" 10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/time/time.h" 1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "gpu/command_buffer/common/command_buffer.h" 1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "gpu/command_buffer/common/trace_event.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gpu { 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommandBufferHelper::CommandBufferHelper(CommandBuffer* command_buffer) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : command_buffer_(command_buffer), 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ring_buffer_id_(-1), 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ring_buffer_size_(0), 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entries_(NULL), 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_entry_count_(0), 225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) immediate_entry_count_(0), 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token_(0), 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) put_(0), 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_put_sent_(0), 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(CMD_HELPER_PERIODIC_FLUSH_CHECK) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) commands_issued_(0), 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usable_(true), 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_lost_(false), 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flush_automatically_(true), 32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) flush_generation_(0) { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferHelper::SetAutomaticFlushes(bool enabled) { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flush_automatically_ = enabled; 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CalcImmediateEntries(0); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CommandBufferHelper::IsContextLost() { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!context_lost_) { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_lost_ = error::IsError(command_buffer()->GetLastError()); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return context_lost_; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CommandBufferHelper::CalcImmediateEntries(int waiting_count) { 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_GE(waiting_count, 0); 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Check if usable & allocated. 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!usable() || !HaveRingBuffer()) { 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) immediate_entry_count_ = 0; 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Get maximum safe contiguous entries. 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const int32 curr_get = get_offset(); 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (curr_get > put_) { 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) immediate_entry_count_ = curr_get - put_ - 1; 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) immediate_entry_count_ = 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) total_entry_count_ - put_ - (curr_get == 0 ? 1 : 0); 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Limit entry count to force early flushing. 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (flush_automatically_) { 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int32 limit = 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) total_entry_count_ / 695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ((curr_get == last_put_sent_) ? kAutoFlushSmall : kAutoFlushBig); 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int32 pending = 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (put_ + total_entry_count_ - last_put_sent_) % total_entry_count_; 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (pending > 0 && pending >= limit) { 755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Time to force flush. 765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) immediate_entry_count_ = 0; 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Limit remaining entries, but not lower than waiting_count entries to 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // prevent deadlock when command size is greater than the flush limit. 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) limit -= pending; 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) limit = limit < waiting_count ? waiting_count : limit; 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) immediate_entry_count_ = 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) immediate_entry_count_ > limit ? limit : immediate_entry_count_; 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CommandBufferHelper::AllocateRingBuffer() { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!usable()) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HaveRingBuffer()) { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32 id = -1; 98effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_refptr<Buffer> buffer = 99effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch command_buffer_->CreateTransferBuffer(ring_buffer_size_, &id); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (id < 0) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClearUsable(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ring_buffer_ = buffer; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ring_buffer_id_ = id; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_buffer_->SetGetBuffer(id); 108effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch entries_ = static_cast<CommandBufferEntry*>(ring_buffer_->memory()); 1090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch total_entry_count_ = ring_buffer_size_ / sizeof(CommandBufferEntry); 1100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Call to SetGetBuffer(id) above resets get and put offsets to 0. 1110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // No need to query it through IPC. 1120529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch put_ = 0; 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CalcImmediateEntries(0); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferHelper::FreeResources() { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HaveRingBuffer()) { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_buffer_->DestroyTransferBuffer(ring_buffer_id_); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ring_buffer_id_ = -1; 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CalcImmediateEntries(0); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferHelper::FreeRingBuffer() { 126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CHECK((put_ == get_offset()) || 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) error::IsError(command_buffer_->GetLastState().error)); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FreeResources(); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CommandBufferHelper::Initialize(int32 ring_buffer_size) { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ring_buffer_size_ = ring_buffer_size; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return AllocateRingBuffer(); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CommandBufferHelper::~CommandBufferHelper() { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FreeResources(); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool CommandBufferHelper::WaitForGetOffsetInRange(int32 start, int32 end) { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!usable()) { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) command_buffer_->WaitForGetOffsetInRange(start, end); 14523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return command_buffer_->GetLastError() == gpu::error::kNoError; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferHelper::Flush() { 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Wrap put_ before flush. 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (put_ == total_entry_count_) 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) put_ = 0; 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (usable() && last_put_sent_ != put_) { 154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch last_flush_time_ = base::TimeTicks::Now(); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_put_sent_ = put_; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_buffer_->Flush(put_); 157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ++flush_generation_; 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CalcImmediateEntries(0); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(CMD_HELPER_PERIODIC_FLUSH_CHECK) 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CommandBufferHelper::PeriodicFlushCheck() { 164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::TimeTicks current_time = base::TimeTicks::Now(); 165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (current_time - last_flush_time_ > 166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::TimeDelta::FromMicroseconds(kPeriodicFlushDelayInMicroseconds)) { 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Flush(); 168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Calls Flush() and then waits until the buffer is empty. Break early if the 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// error is set. 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CommandBufferHelper::Finish() { 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRACE_EVENT0("gpu", "CommandBufferHelper::Finish"); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!usable()) { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there is no work just exit. 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (put_ == get_offset()) { 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(HaveRingBuffer()); 18423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) Flush(); 18523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!WaitForGetOffsetInRange(put_, put_)) 18623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return false; 18723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) DCHECK_EQ(get_offset(), put_); 18823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 18923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) CalcImmediateEntries(0); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Inserts a new token into the command stream. It uses an increasing value 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// scheme so that we don't lose tokens (a token has passed if the current token 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// value is higher than that token). Calls Finish() if the token value wraps, 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// which will be rare. 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32 CommandBufferHelper::InsertToken() { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AllocateRingBuffer(); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!usable()) { 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return token_; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(HaveRingBuffer()); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Increment token as 31-bit integer. Negative values are used to signal an 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // error. 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token_ = (token_ + 1) & 0x7FFFFFFF; 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd::SetToken* cmd = GetCmdSpace<cmd::SetToken>(); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cmd) { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd->Init(token_); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (token_ == 0) { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRACE_EVENT0("gpu", "CommandBufferHelper::InsertToken(wrapped)"); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we wrapped 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Finish(); 214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK_EQ(token_, last_token_read()); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return token_; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Waits until the current token value is greater or equal to the value passed 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in argument. 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferHelper::WaitForToken(int32 token) { 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!usable() || !HaveRingBuffer()) { 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return immediately if corresponding InsertToken failed. 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (token < 0) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (token > token_) return; // we wrapped 230010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if (last_token_read() >= token) 23123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return; 23223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) Flush(); 23323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) command_buffer_->WaitForTokenInRange(token, token_); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Waits for available entries, basically waiting until get >= put + count + 1. 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It actually waits for contiguous entries, so it may need to wrap the buffer 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// around, adding a noops. Thus this function may change the value of put_. The 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// function will return early if an error occurs, in which case the available 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// space may not be available. 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CommandBufferHelper::WaitForAvailableEntries(int32 count) { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AllocateRingBuffer(); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!usable()) { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 246f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(HaveRingBuffer()); 247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(count < total_entry_count_); 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (put_ + count > total_entry_count_) { 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There's not enough room between the current put and the end of the 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // buffer, so we need to wrap. We will add noops all the way to the end, 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // but we need to make sure get wraps first, actually that get is 1 or 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // more (since put will wrap to 0 after we add the noops). 253f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK_LE(1, put_); 2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int32 curr_get = get_offset(); 2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (curr_get > put_ || curr_get == 0) { 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TRACE_EVENT0("gpu", "CommandBufferHelper::WaitForAvailableEntries"); 25723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) Flush(); 25823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!WaitForGetOffsetInRange(1, put_)) 25923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return; 26023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) curr_get = get_offset(); 26123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) DCHECK_LE(curr_get, put_); 26223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) DCHECK_NE(0, curr_get); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Insert Noops to fill out the buffer. 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32 num_entries = total_entry_count_ - put_; 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (num_entries > 0) { 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32 num_to_skip = std::min(CommandHeader::kMaxSize, num_entries); 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cmd::Noop::Set(&entries_[put_], num_to_skip); 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) put_ += num_to_skip; 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) num_entries -= num_to_skip; 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) put_ = 0; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Try to get 'count' entries without flushing. 2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CalcImmediateEntries(count); 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (immediate_entry_count_ < count) { 2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Try again with a shallow Flush(). 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Flush(); 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CalcImmediateEntries(count); 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (immediate_entry_count_ < count) { 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Buffer is full. Need to wait for entries. 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) TRACE_EVENT0("gpu", "CommandBufferHelper::WaitForAvailableEntries1"); 28423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!WaitForGetOffsetInRange(put_ + count + 1, put_)) 28523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return; 28623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) CalcImmediateEntries(count); 28723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) DCHECK_GE(immediate_entry_count_, count); 2885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace gpu 294