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