blob: 3a48bbf7afb19869dc2b293ed7de7faac8e3a80d [file] [log] [blame]
// Copyright 2018 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.
#include "gpu/command_buffer/common/skia_utils.h"
#include "base/system/sys_info.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/process_memory_dump.h"
#include "build/build_config.h"
#include "third_party/skia/include/core/SkTraceMemoryDump.h"
#include "third_party/skia/include/gpu/GrContext.h"
#include "ui/gl/trace_util.h"
namespace gpu {
namespace raster {
namespace {
// Derives from SkTraceMemoryDump and implements graphics specific memory
// backing functionality.
class SkiaGpuTraceMemoryDump : public SkTraceMemoryDump {
public:
// This should never outlive the provided ProcessMemoryDump, as it should
// always be scoped to a single OnMemoryDump funciton call.
SkiaGpuTraceMemoryDump(base::trace_event::ProcessMemoryDump* pmd,
base::Optional<uint64_t> share_group_tracing_guid)
: pmd_(pmd),
share_group_tracing_guid_(share_group_tracing_guid),
tracing_process_id_(base::trace_event::MemoryDumpManager::GetInstance()
->GetTracingProcessId()) {}
~SkiaGpuTraceMemoryDump() override = default;
// Overridden from SkTraceMemoryDump:
void dumpNumericValue(const char* dump_name,
const char* value_name,
const char* units,
uint64_t value) override {
auto* dump = GetOrCreateAllocatorDump(dump_name);
dump->AddScalar(value_name, units, value);
}
void setMemoryBacking(const char* dump_name,
const char* backing_type,
const char* backing_object_id) override {
// For uniformity, skia provides this value as a string. Convert back to a
// uint32_t.
uint32_t gl_id =
std::strtoul(backing_object_id, nullptr /* str_end */, 10 /* base */);
// Constants used by SkiaGpuTraceMemoryDump to identify different memory
// types.
const char* kGLTextureBackingType = "gl_texture";
const char* kGLBufferBackingType = "gl_buffer";
const char* kGLRenderbufferBackingType = "gl_renderbuffer";
// Populated in if statements below.
base::trace_event::MemoryAllocatorDumpGuid guid;
if (share_group_tracing_guid_) {
// If we have a |share_group_tracing_guid_|, we are in a render process
// and need to create client texture GUIDs for aliasing with the GPU
// process.
if (strcmp(backing_type, kGLTextureBackingType) == 0) {
guid = gl::GetGLTextureClientGUIDForTracing(*share_group_tracing_guid_,
gl_id);
} else if (strcmp(backing_type, kGLBufferBackingType) == 0) {
guid = gl::GetGLBufferGUIDForTracing(tracing_process_id_, gl_id);
} else if (strcmp(backing_type, kGLRenderbufferBackingType) == 0) {
guid = gl::GetGLRenderbufferGUIDForTracing(tracing_process_id_, gl_id);
}
} else {
// If we do not have a |share_group_tracing_guid_|, we are in the GPU
// process, being used for OOP-R. We need to create Raster dumps for
// aliasing with the transfer cache. Note that this is currently only
// needed for textures (not buffers or renderbuffers).
if (strcmp(backing_type, kGLTextureBackingType) == 0) {
guid = gl::GetGLTextureRasterGUIDForTracing(gl_id);
}
}
if (!guid.empty()) {
pmd_->CreateSharedGlobalAllocatorDump(guid);
auto* dump = GetOrCreateAllocatorDump(dump_name);
const int kImportance = 2;
pmd_->AddOwnershipEdge(dump->guid(), guid, kImportance);
}
}
void setDiscardableMemoryBacking(
const char* dump_name,
const SkDiscardableMemory& discardable_memory_object) override {
// We don't use this class for dumping discardable memory.
NOTREACHED();
}
LevelOfDetail getRequestedDetails() const override {
// TODO(ssid): Use MemoryDumpArgs to create light dumps when requested
// (crbug.com/499731).
return kObjectsBreakdowns_LevelOfDetail;
}
bool shouldDumpWrappedObjects() const override {
// Chrome already dumps objects it imports into Skia. Avoid duplicate dumps
// by asking Skia not to dump them.
return false;
}
private:
// Helper to create allocator dumps.
base::trace_event::MemoryAllocatorDump* GetOrCreateAllocatorDump(
const char* dump_name) {
auto* dump = pmd_->GetAllocatorDump(dump_name);
if (!dump)
dump = pmd_->CreateAllocatorDump(dump_name);
return dump;
}
base::trace_event::ProcessMemoryDump* pmd_;
base::Optional<uint64_t> share_group_tracing_guid_;
uint64_t tracing_process_id_;
DISALLOW_COPY_AND_ASSIGN(SkiaGpuTraceMemoryDump);
};
} // namespace
void DetermineGrCacheLimitsFromAvailableMemory(
size_t* max_resource_cache_bytes,
size_t* max_glyph_cache_texture_bytes) {
// Default limits.
constexpr size_t kMaxGaneshResourceCacheBytes = 96 * 1024 * 1024;
constexpr size_t kMaxDefaultGlyphCacheTextureBytes = 2048 * 1024 * 4;
*max_resource_cache_bytes = kMaxGaneshResourceCacheBytes;
*max_glyph_cache_texture_bytes = kMaxDefaultGlyphCacheTextureBytes;
// We can't call AmountOfPhysicalMemory under NACL, so leave the default.
#if !defined(OS_NACL)
// The limit of the bytes allocated toward GPU resources in the GrContext's
// GPU cache.
constexpr size_t kMaxLowEndGaneshResourceCacheBytes = 48 * 1024 * 1024;
constexpr size_t kMaxHighEndGaneshResourceCacheBytes = 256 * 1024 * 1024;
// Limits for glyph cache textures.
constexpr size_t kMaxLowEndGlyphCacheTextureBytes = 1024 * 512 * 4;
// High-end / low-end memory cutoffs.
constexpr int64_t kHighEndMemoryThreshold = (int64_t)4096 * 1024 * 1024;
constexpr int64_t kLowEndMemoryThreshold = (int64_t)512 * 1024 * 1024;
int64_t amount_of_physical_memory = base::SysInfo::AmountOfPhysicalMemory();
if (amount_of_physical_memory <= kLowEndMemoryThreshold) {
*max_resource_cache_bytes = kMaxLowEndGaneshResourceCacheBytes;
*max_glyph_cache_texture_bytes = kMaxLowEndGlyphCacheTextureBytes;
} else if (amount_of_physical_memory >= kHighEndMemoryThreshold) {
*max_resource_cache_bytes = kMaxHighEndGaneshResourceCacheBytes;
}
#endif
}
void DefaultGrCacheLimitsForTests(size_t* max_resource_cache_bytes,
size_t* max_glyph_cache_texture_bytes) {
constexpr size_t kDefaultGlyphCacheTextureBytes = 2048 * 1024 * 4;
constexpr size_t kDefaultGaneshResourceCacheBytes = 96 * 1024 * 1024;
*max_resource_cache_bytes = kDefaultGaneshResourceCacheBytes;
*max_glyph_cache_texture_bytes = kDefaultGlyphCacheTextureBytes;
}
void DumpGrMemoryStatistics(const GrContext* context,
base::trace_event::ProcessMemoryDump* pmd,
base::Optional<uint64_t> tracing_guid) {
SkiaGpuTraceMemoryDump trace_memory_dump(pmd, tracing_guid);
context->dumpMemoryStatistics(&trace_memory_dump);
}
} // namespace raster
} // namespace gpu