cmd_buffer_helper.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Copyright (c) 2012 The Chromium Authors. All rights reserved.
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Use of this source code is governed by a BSD-style license that can be
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// found in the LICENSE file.
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// This file contains the implementation of the command buffer helper class.
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gpu/command_buffer/client/cmd_buffer_helper.h"
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gpu/command_buffer/common/command_buffer.h"
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "gpu/command_buffer/common/trace_event.h"
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace gpu {
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace {
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst int kCommandsPerFlushCheck = 100;
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst double kFlushDelay = 1.0 / (5.0 * 60.0);
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
183c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCommandBufferHelper::CommandBufferHelper(CommandBuffer* command_buffer)
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    : command_buffer_(command_buffer),
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      ring_buffer_id_(-1),
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      ring_buffer_size_(0),
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      entries_(NULL),
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      total_entry_count_(0),
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      token_(0),
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      put_(0),
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      last_put_sent_(0),
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      commands_issued_(0),
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      usable_(true),
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      context_lost_(false),
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      flush_automatically_(true),
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      last_flush_time_(0) {
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid CommandBufferHelper::SetAutomaticFlushes(bool enabled) {
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  flush_automatically_ = enabled;
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool CommandBufferHelper::IsContextLost() {
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (!context_lost_) {
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    context_lost_ = error::IsError(command_buffer()->GetLastError());
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return context_lost_;
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool CommandBufferHelper::AllocateRingBuffer() {
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (!usable()) {
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return false;
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (HaveRingBuffer()) {
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return true;
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  int32 id = -1;
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  Buffer buffer = command_buffer_->CreateTransferBuffer(ring_buffer_size_, &id);
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (id < 0) {
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    ClearUsable();
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return false;
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  ring_buffer_ = buffer;
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  ring_buffer_id_ = id;
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  command_buffer_->SetGetBuffer(id);
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // TODO(gman): Do we really need to call GetState here? We know get & put = 0
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // Also do we need to check state.num_entries?
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CommandBuffer::State state = command_buffer_->GetState();
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  entries_ = static_cast<CommandBufferEntry*>(ring_buffer_.ptr);
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  int32 num_ring_buffer_entries =
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      ring_buffer_size_ / sizeof(CommandBufferEntry);
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (num_ring_buffer_entries > state.num_entries) {
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    ClearUsable();
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return false;
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  total_entry_count_ = num_ring_buffer_entries;
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  put_ = state.put_offset;
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return true;
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid CommandBufferHelper::FreeResources() {
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (HaveRingBuffer()) {
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    command_buffer_->DestroyTransferBuffer(ring_buffer_id_);
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    ring_buffer_id_ = -1;
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid CommandBufferHelper::FreeRingBuffer() {
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  GPU_CHECK((put_ == get_offset()) ||
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      error::IsError(command_buffer_->GetLastState().error));
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  FreeResources();
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool CommandBufferHelper::Initialize(int32 ring_buffer_size) {
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  ring_buffer_size_ = ring_buffer_size;
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return AllocateRingBuffer();
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
993c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCommandBufferHelper::~CommandBufferHelper() {
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  FreeResources();
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool CommandBufferHelper::FlushSync() {
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (!usable()) {
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return false;
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  last_flush_time_ = clock();
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  last_put_sent_ = put_;
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CommandBuffer::State state = command_buffer_->FlushSync(put_, get_offset());
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return state.error == error::kNoError;
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid CommandBufferHelper::Flush() {
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (usable() && last_put_sent_ != put_) {
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    last_flush_time_ = clock();
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    last_put_sent_ = put_;
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    command_buffer_->Flush(put_);
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Calls Flush() and then waits until the buffer is empty. Break early if the
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// error is set.
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool CommandBufferHelper::Finish() {
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  TRACE_EVENT0("gpu", "CommandBufferHelper::Finish");
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (!usable()) {
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return false;
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // If there is no work just exit.
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (put_ == get_offset()) {
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return true;
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  GPU_DCHECK(HaveRingBuffer());
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  do {
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // Do not loop forever if the flush fails, meaning the command buffer reader
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // has shutdown.
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (!FlushSync())
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      return false;
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  } while (put_ != get_offset());
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return true;
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Inserts a new token into the command stream. It uses an increasing value
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// scheme so that we don't lose tokens (a token has passed if the current token
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// value is higher than that token). Calls Finish() if the token value wraps,
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// which will be rare.
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint32 CommandBufferHelper::InsertToken() {
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  AllocateRingBuffer();
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (!usable()) {
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return token_;
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  GPU_DCHECK(HaveRingBuffer());
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // Increment token as 31-bit integer. Negative values are used to signal an
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // error.
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  token_ = (token_ + 1) & 0x7FFFFFFF;
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  cmd::SetToken* cmd = GetCmdSpace<cmd::SetToken>();
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (cmd) {
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    cmd->Init(token_);
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (token_ == 0) {
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      TRACE_EVENT0("gpu", "CommandBufferHelper::InsertToken(wrapped)");
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      // we wrapped
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      Finish();
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      GPU_DCHECK_EQ(token_, last_token_read());
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    }
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return token_;
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Waits until the current token value is greater or equal to the value passed
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// in argument.
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid CommandBufferHelper::WaitForToken(int32 token) {
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (!usable() || !HaveRingBuffer()) {
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return;
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // Return immediately if corresponding InsertToken failed.
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (token < 0)
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return;
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (token > token_) return;  // we wrapped
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  while (last_token_read() < token) {
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (get_offset() == put_) {
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      GPU_LOG(FATAL) << "Empty command buffer while waiting on a token.";
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      return;
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    }
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // Do not loop forever if the flush fails, meaning the command buffer reader
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // has shutdown.
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (!FlushSync())
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      return;
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Waits for available entries, basically waiting until get >= put + count + 1.
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// It actually waits for contiguous entries, so it may need to wrap the buffer
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// around, adding a noops. Thus this function may change the value of put_. The
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// function will return early if an error occurs, in which case the available
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// space may not be available.
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid CommandBufferHelper::WaitForAvailableEntries(int32 count) {
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  AllocateRingBuffer();
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (!usable()) {
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return;
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  GPU_DCHECK(HaveRingBuffer());
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  GPU_DCHECK(count < total_entry_count_);
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (put_ + count > total_entry_count_) {
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // There's not enough room between the current put and the end of the
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // buffer, so we need to wrap. We will add noops all the way to the end,
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // but we need to make sure get wraps first, actually that get is 1 or
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // more (since put will wrap to 0 after we add the noops).
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    GPU_DCHECK_LE(1, put_);
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (get_offset() > put_ || get_offset() == 0) {
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      TRACE_EVENT0("gpu", "CommandBufferHelper::WaitForAvailableEntries");
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      while (get_offset() > put_ || get_offset() == 0) {
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry        // Do not loop forever if the flush fails, meaning the command buffer
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry        // reader has shutdown.
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry        if (!FlushSync())
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry          return;
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      }
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    }
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // Insert Noops to fill out the buffer.
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    int32 num_entries = total_entry_count_ - put_;
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    while (num_entries > 0) {
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      int32 num_to_skip = std::min(CommandHeader::kMaxSize, num_entries);
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      cmd::Noop::Set(&entries_[put_], num_to_skip);
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      put_ += num_to_skip;
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      num_entries -= num_to_skip;
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    }
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    put_ = 0;
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (AvailableEntries() < count) {
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    TRACE_EVENT0("gpu", "CommandBufferHelper::WaitForAvailableEntries1");
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    while (AvailableEntries() < count) {
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      // Do not loop forever if the flush fails, meaning the command buffer
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      // reader has shutdown.
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      if (!FlushSync())
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry        return;
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    }
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // Force a flush if the buffer is getting half full, or even earlier if the
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // reader is known to be idle.
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  int32 pending =
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      (put_ + total_entry_count_ - last_put_sent_) % total_entry_count_;
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  int32 limit = total_entry_count_ /
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      ((get_offset() == last_put_sent_) ? 16 : 2);
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (pending > limit) {
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    Flush();
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  } else if (flush_automatically_ &&
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry             (commands_issued_ % kCommandsPerFlushCheck == 0)) {
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if !defined(OS_ANDROID)
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // Allow this command buffer to be pre-empted by another if a "reasonable"
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // amount of work has been done. On highend machines, this reduces the
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // latency of GPU commands. However, on Android, this can cause the
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // kernel to thrash between generating GPU commands and executing them.
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    clock_t current_time = clock();
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (current_time - last_flush_time_ > kFlushDelay * CLOCKS_PER_SEC)
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      Flush();
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2593c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCommandBufferEntry* CommandBufferHelper::GetSpace(uint32 entries) {
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  AllocateRingBuffer();
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (!usable()) {
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return NULL;
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  GPU_DCHECK(HaveRingBuffer());
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  ++commands_issued_;
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  WaitForAvailableEntries(entries);
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CommandBufferEntry* space = &entries_[put_];
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  put_ += entries;
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  GPU_DCHECK_LE(put_, total_entry_count_);
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (put_ == total_entry_count_) {
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    put_ = 0;
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return space;
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyryerror::Error CommandBufferHelper::GetError() {
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CommandBuffer::State state = command_buffer_->GetState();
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return static_cast<error::Error>(state.error);
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}  // namespace gpu
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry