blob: 7eeee65d5edbba52fb7c9b4fe3060fb08497ac36 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef GPU_COMMAND_BUFFER_CLIENT_MAPPED_MEMORY_H_
#define GPU_COMMAND_BUFFER_CLIENT_MAPPED_MEMORY_H_
#include <stddef.h>
#include <stdint.h>
#include <memory>
#include "base/bind.h"
#include "base/macros.h"
#include "base/trace_event/memory_dump_provider.h"
#include "gpu/command_buffer/client/fenced_allocator.h"
#include "gpu/command_buffer/common/buffer.h"
#include "gpu/gpu_export.h"
namespace gpu {
class CommandBufferHelper;
// Manages a shared memory segment.
class GPU_EXPORT MemoryChunk {
public:
MemoryChunk(int32_t shm_id,
scoped_refptr<gpu::Buffer> shm,
CommandBufferHelper* helper);
~MemoryChunk();
// Gets the size of the largest free block that is available without waiting.
unsigned int GetLargestFreeSizeWithoutWaiting() {
return allocator_.GetLargestFreeSize();
}
// Gets the size of the largest free block that can be allocated if the
// caller can wait.
unsigned int GetLargestFreeSizeWithWaiting() {
return allocator_.GetLargestFreeOrPendingSize();
}
// Gets the size of the chunk.
unsigned int GetSize() const {
return static_cast<unsigned int>(shm_->size());
}
// The shared memory id for this chunk.
int32_t shm_id() const {
return shm_id_;
}
gpu::Buffer* shared_memory() const { return shm_.get(); }
// Allocates a block of memory. If the buffer is out of directly available
// memory, this function may wait until memory that was freed "pending a
// token" can be re-used.
//
// Parameters:
// size: the size of the memory block to allocate.
//
// Returns:
// the pointer to the allocated memory block, or nullptr if out of
// memory.
void* Alloc(unsigned int size) {
return allocator_.Alloc(size);
}
// Gets the offset to a memory block given the base memory and the address.
// It translates nullptr to FencedAllocator::kInvalidOffset.
unsigned int GetOffset(void* pointer) {
return allocator_.GetOffset(pointer);
}
// Frees a block of memory.
//
// Parameters:
// pointer: the pointer to the memory block to free.
void Free(void* pointer) {
allocator_.Free(pointer);
}
// Frees a block of memory, pending the passage of a token. That memory won't
// be re-allocated until the token has passed through the command stream.
//
// Parameters:
// pointer: the pointer to the memory block to free.
// token: the token value to wait for before re-using the memory.
void FreePendingToken(void* pointer, unsigned int token) {
allocator_.FreePendingToken(pointer, token);
}
// Frees any blocks whose tokens have passed.
void FreeUnused() {
allocator_.FreeUnused();
}
// Gets the free size of the chunk.
unsigned int GetFreeSize() { return allocator_.GetFreeSize(); }
// Returns true if pointer is in the range of this block.
bool IsInChunk(void* pointer) const {
return pointer >= shm_->memory() &&
pointer < static_cast<const int8_t*>(shm_->memory()) + shm_->size();
}
// Returns true of any memory in this chunk is in use or free pending token.
bool InUseOrFreePending() { return allocator_.InUseOrFreePending(); }
size_t bytes_in_use() const {
return allocator_.bytes_in_use();
}
FencedAllocator::State GetPointerStatusForTest(void* pointer,
int32_t* token_if_pending) {
return allocator_.GetPointerStatusForTest(pointer, token_if_pending);
}
private:
int32_t shm_id_;
scoped_refptr<gpu::Buffer> shm_;
FencedAllocatorWrapper allocator_;
DISALLOW_COPY_AND_ASSIGN(MemoryChunk);
};
// Manages MemoryChunks.
class GPU_EXPORT MappedMemoryManager {
public:
enum MemoryLimit {
kNoLimit = 0,
};
// |unused_memory_reclaim_limit|: When exceeded this causes pending memory
// to be reclaimed before allocating more memory.
MappedMemoryManager(CommandBufferHelper* helper,
size_t unused_memory_reclaim_limit);
~MappedMemoryManager();
unsigned int chunk_size_multiple() const {
return chunk_size_multiple_;
}
void set_chunk_size_multiple(unsigned int multiple) {
DCHECK(multiple % FencedAllocator::kAllocAlignment == 0);
chunk_size_multiple_ = multiple;
}
size_t max_allocated_bytes() const {
return max_allocated_bytes_;
}
void set_max_allocated_bytes(size_t max_allocated_bytes) {
max_allocated_bytes_ = max_allocated_bytes;
}
// Allocates a block of memory
// Parameters:
// size: size of memory to allocate.
// shm_id: pointer to variable to receive the shared memory id.
// shm_offset: pointer to variable to receive the shared memory offset.
// Returns:
// pointer to allocated block of memory. nullptr if failure.
void* Alloc(
unsigned int size, int32_t* shm_id, unsigned int* shm_offset);
// Frees a block of memory.
//
// Parameters:
// pointer: the pointer to the memory block to free.
void Free(void* pointer);
// Frees a block of memory, pending the passage of a token. That memory won't
// be re-allocated until the token has passed through the command stream.
//
// Parameters:
// pointer: the pointer to the memory block to free.
// token: the token value to wait for before re-using the memory.
void FreePendingToken(void* pointer, int32_t token);
// Free Any Shared memory that is not in use.
void FreeUnused();
// Dump memory usage - called from GLES2Implementation.
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd);
// Used for testing
size_t num_chunks() const {
return chunks_.size();
}
size_t bytes_in_use() const {
size_t bytes_in_use = 0;
for (size_t ii = 0; ii < chunks_.size(); ++ii) {
bytes_in_use += chunks_[ii]->bytes_in_use();
}
return bytes_in_use;
}
// Used for testing
size_t allocated_memory() const {
return allocated_memory_;
}
// Gets the status of a previous allocation, as well as the corresponding
// token if FREE_PENDING_TOKEN (and token_if_pending is not null).
FencedAllocator::State GetPointerStatusForTest(void* pointer,
int32_t* token_if_pending);
private:
typedef std::vector<std::unique_ptr<MemoryChunk>> MemoryChunkVector;
// size a chunk is rounded up to.
unsigned int chunk_size_multiple_;
CommandBufferHelper* helper_;
MemoryChunkVector chunks_;
size_t allocated_memory_;
size_t max_free_bytes_;
size_t max_allocated_bytes_;
// A process-unique ID used for disambiguating memory dumps from different
// mapped memory manager.
int tracing_id_;
DISALLOW_COPY_AND_ASSIGN(MappedMemoryManager);
};
// A class that will manage the lifetime of a mapped memory allocation
class GPU_EXPORT ScopedMappedMemoryPtr {
public:
ScopedMappedMemoryPtr(uint32_t size,
CommandBufferHelper* helper,
MappedMemoryManager* mapped_memory_manager)
: buffer_(nullptr),
size_(0),
shm_id_(0),
shm_offset_(0),
flush_after_release_(false),
helper_(helper),
mapped_memory_manager_(mapped_memory_manager) {
Reset(size);
}
~ScopedMappedMemoryPtr() {
Release();
}
bool valid() const { return buffer_ != nullptr; }
void SetFlushAfterRelease(bool flush_after_release) {
flush_after_release_ = flush_after_release;
}
uint32_t size() const {
return size_;
}
int32_t shm_id() const {
return shm_id_;
}
uint32_t offset() const {
return shm_offset_;
}
void* address() const {
return buffer_;
}
void Release();
void Reset(uint32_t new_size);
private:
void* buffer_;
uint32_t size_;
int32_t shm_id_;
uint32_t shm_offset_;
bool flush_after_release_;
CommandBufferHelper* helper_;
MappedMemoryManager* mapped_memory_manager_;
DISALLOW_COPY_AND_ASSIGN(ScopedMappedMemoryPtr);
};
} // namespace gpu
#endif // GPU_COMMAND_BUFFER_CLIENT_MAPPED_MEMORY_H_