15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 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) 590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "gpu/command_buffer/client/mapped_memory.h" 690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <functional> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/debug/trace_event.h" 11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/logging.h" 1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "gpu/command_buffer/client/cmd_buffer_helper.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gpu { 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochMemoryChunk::MemoryChunk(int32 shm_id, 17effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_refptr<gpu::Buffer> shm, 184ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch CommandBufferHelper* helper, 194ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch const base::Closure& poll_callback) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : shm_id_(shm_id), 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shm_(shm), 224ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch allocator_(shm->size(), helper, poll_callback, shm->memory()) {} 23effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 24effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochMemoryChunk::~MemoryChunk() {} 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)MappedMemoryManager::MappedMemoryManager(CommandBufferHelper* helper, 274ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch const base::Closure& poll_callback, 283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) size_t unused_memory_reclaim_limit) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : chunk_size_multiple_(1), 303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) helper_(helper), 314ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch poll_callback_(poll_callback), 323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) allocated_memory_(0), 333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) max_free_bytes_(unused_memory_reclaim_limit) { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MappedMemoryManager::~MappedMemoryManager() { 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CommandBuffer* cmd_buf = helper_->command_buffer(); 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (MemoryChunkVector::iterator iter = chunks_.begin(); 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) iter != chunks_.end(); ++iter) { 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MemoryChunk* chunk = *iter; 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cmd_buf->DestroyTransferBuffer(chunk->shm_id()); 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* MappedMemoryManager::Alloc( 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int size, int32* shm_id, unsigned int* shm_offset) { 47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(shm_id); 48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(shm_offset); 493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (size <= allocated_memory_) { 503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) size_t total_bytes_in_use = 0; 513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // See if any of the chunks can satisfy this request. 523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (size_t ii = 0; ii < chunks_.size(); ++ii) { 533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) MemoryChunk* chunk = chunks_[ii]; 543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) chunk->FreeUnused(); 553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) total_bytes_in_use += chunk->bytes_in_use(); 563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (chunk->GetLargestFreeSizeWithoutWaiting() >= size) { 573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) void* mem = chunk->Alloc(size); 58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(mem); 593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *shm_id = chunk->shm_id(); 603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *shm_offset = chunk->GetOffset(mem); 613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return mem; 623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // If there is a memory limit being enforced and total free 663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // memory (allocated_memory_ - total_bytes_in_use) is larger than 673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // the limit try waiting. 683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (max_free_bytes_ != kNoLimit && 693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) (allocated_memory_ - total_bytes_in_use) >= max_free_bytes_) { 703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) TRACE_EVENT0("gpu", "MappedMemoryManager::Alloc::wait"); 713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (size_t ii = 0; ii < chunks_.size(); ++ii) { 723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) MemoryChunk* chunk = chunks_[ii]; 733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (chunk->GetLargestFreeSizeWithWaiting() >= size) { 743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) void* mem = chunk->Alloc(size); 75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(mem); 763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *shm_id = chunk->shm_id(); 773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *shm_offset = chunk->GetOffset(mem); 783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return mem; 793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make a new chunk to satisfy the request. 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandBuffer* cmd_buf = helper_->command_buffer(); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int chunk_size = 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((size + chunk_size_multiple_ - 1) / chunk_size_multiple_) * 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chunk_size_multiple_; 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32 id = -1; 90effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_refptr<gpu::Buffer> shm = 91effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch cmd_buf->CreateTransferBuffer(chunk_size, &id); 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (id < 0) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 94e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK(shm); 954ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch MemoryChunk* mc = new MemoryChunk(id, shm, helper_, poll_callback_); 963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) allocated_memory_ += mc->GetSize(); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chunks_.push_back(mc); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* mem = mc->Alloc(size); 99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(mem); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *shm_id = mc->shm_id(); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *shm_offset = mc->GetOffset(mem); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mem; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MappedMemoryManager::Free(void* pointer) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t ii = 0; ii < chunks_.size(); ++ii) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MemoryChunk* chunk = chunks_[ii]; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (chunk->IsInChunk(pointer)) { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chunk->Free(pointer); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) NOTREACHED(); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MappedMemoryManager::FreePendingToken(void* pointer, int32 token) { 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t ii = 0; ii < chunks_.size(); ++ii) { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MemoryChunk* chunk = chunks_[ii]; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (chunk->IsInChunk(pointer)) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chunk->FreePendingToken(pointer, token); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) NOTREACHED(); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MappedMemoryManager::FreeUnused() { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandBuffer* cmd_buf = helper_->command_buffer(); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MemoryChunkVector::iterator iter = chunks_.begin(); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (iter != chunks_.end()) { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MemoryChunk* chunk = *iter; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chunk->FreeUnused(); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!chunk->InUse()) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmd_buf->DestroyTransferBuffer(chunk->shm_id()); 1353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) allocated_memory_ -= chunk->GetSize(); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter = chunks_.erase(iter); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++iter; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace gpu 144