GpuMemoryTracker.cpp revision 38e0c32852e3b9d8ca4a9d3791577f52536419cb
138e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck/* 238e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck * Copyright (C) 2016 The Android Open Source Project 338e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck * 438e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck * Licensed under the Apache License, Version 2.0 (the "License"); 538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck * you may not use this file except in compliance with the License. 638e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck * You may obtain a copy of the License at 738e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck * 838e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck * http://www.apache.org/licenses/LICENSE-2.0 938e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck * 1038e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck * Unless required by applicable law or agreed to in writing, software 1138e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck * distributed under the License is distributed on an "AS IS" BASIS, 1238e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1338e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck * See the License for the specific language governing permissions and 1438e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck * limitations under the License. 1538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck */ 1638e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck 1738e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck#include "utils/StringUtils.h" 1838e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck#include "Texture.h" 1938e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck 2038e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck#include <cutils/compiler.h> 2138e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck#include <GpuMemoryTracker.h> 2238e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck#include <utils/Trace.h> 2338e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck#include <array> 2438e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck#include <sstream> 2538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck#include <unordered_set> 2638e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck#include <vector> 2738e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck 2838e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Recknamespace android { 2938e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Recknamespace uirenderer { 3038e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck 3138e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reckpthread_t gGpuThread = 0; 3238e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck 3338e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck#define NUM_TYPES static_cast<int>(GpuObjectType::TypeCount) 3438e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck 3538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reckconst char* TYPE_NAMES[] = { 3638e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck "Texture", 3738e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck "OffscreenBuffer", 3838e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck "Layer", 3938e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck}; 4038e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck 4138e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reckstruct TypeStats { 4238e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck int totalSize = 0; 4338e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck int count = 0; 4438e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck}; 4538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck 4638e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reckstatic std::array<TypeStats, NUM_TYPES> gObjectStats; 4738e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reckstatic std::unordered_set<GpuMemoryTracker*> gObjectSet; 4838e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck 4938e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reckvoid GpuMemoryTracker::notifySizeChanged(int newSize) { 5038e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck int delta = newSize - mSize; 5138e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck mSize = newSize; 5238e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck gObjectStats[static_cast<int>(mType)].totalSize += delta; 5338e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck} 5438e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck 5538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reckvoid GpuMemoryTracker::startTrackingObject() { 5638e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck auto result = gObjectSet.insert(this); 5738e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck LOG_ALWAYS_FATAL_IF(!result.second, 5838e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck "startTrackingObject() on %p failed, already being tracked!", this); 5938e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck gObjectStats[static_cast<int>(mType)].count++; 6038e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck} 6138e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck 6238e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reckvoid GpuMemoryTracker::stopTrackingObject() { 6338e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck size_t removed = gObjectSet.erase(this); 6438e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck LOG_ALWAYS_FATAL_IF(removed != 1, 6538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck "stopTrackingObject removed %zd, is %p not being tracked?", 6638e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck removed, this); 6738e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck gObjectStats[static_cast<int>(mType)].count--; 6838e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck} 6938e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck 7038e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reckvoid GpuMemoryTracker::onGLContextCreated() { 7138e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck LOG_ALWAYS_FATAL_IF(gGpuThread != 0, "We already have a GL thread? " 7238e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck "current = %lu, gl thread = %lu", pthread_self(), gGpuThread); 7338e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck gGpuThread = pthread_self(); 7438e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck} 7538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck 7638e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reckvoid GpuMemoryTracker::onGLContextDestroyed() { 7738e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck gGpuThread = 0; 7838e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck if (CC_UNLIKELY(gObjectSet.size() > 0)) { 7938e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck std::stringstream os; 8038e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck dump(os); 8138e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck ALOGE("%s", os.str().c_str()); 8238e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck LOG_ALWAYS_FATAL("Leaked %zd GPU objects!", gObjectSet.size()); 8338e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck } 8438e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck} 8538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck 8638e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reckvoid GpuMemoryTracker::dump() { 8738e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck std::stringstream strout; 8838e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck dump(strout); 8938e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck ALOGD("%s", strout.str().c_str()); 9038e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck} 9138e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck 9238e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reckvoid GpuMemoryTracker::dump(std::ostream& stream) { 9338e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck for (int type = 0; type < NUM_TYPES; type++) { 9438e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck const TypeStats& stats = gObjectStats[type]; 9538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck stream << TYPE_NAMES[type]; 9638e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck stream << " is using " << SizePrinter{stats.totalSize}; 9738e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck stream << ", count = " << stats.count; 9838e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck stream << std::endl; 9938e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck } 10038e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck} 10138e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck 10238e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reckint GpuMemoryTracker::getInstanceCount(GpuObjectType type) { 10338e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck return gObjectStats[static_cast<int>(type)].count; 10438e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck} 10538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck 10638e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reckint GpuMemoryTracker::getTotalSize(GpuObjectType type) { 10738e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck return gObjectStats[static_cast<int>(type)].totalSize; 10838e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck} 10938e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck 11038e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reckvoid GpuMemoryTracker::onFrameCompleted() { 11138e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck if (ATRACE_ENABLED()) { 11238e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck char buf[128]; 11338e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck for (int type = 0; type < NUM_TYPES; type++) { 11438e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck snprintf(buf, 128, "hwui_%s", TYPE_NAMES[type]); 11538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck const TypeStats& stats = gObjectStats[type]; 11638e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck ATRACE_INT(buf, stats.totalSize); 11738e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck snprintf(buf, 128, "hwui_%s_count", TYPE_NAMES[type]); 11838e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck ATRACE_INT(buf, stats.count); 11938e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck } 12038e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck } 12138e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck 12238e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck std::vector<const Texture*> freeList; 12338e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck for (const auto& obj : gObjectSet) { 12438e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck if (obj->objectType() == GpuObjectType::Texture) { 12538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck const Texture* texture = static_cast<Texture*>(obj); 12638e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck if (texture->cleanup) { 12738e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck ALOGE("Leaked texture marked for cleanup! id=%u, size %ux%u", 12838e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck texture->id(), texture->width(), texture->height()); 12938e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck freeList.push_back(texture); 13038e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck } 13138e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck } 13238e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck } 13338e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck for (auto& texture : freeList) { 13438e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck const_cast<Texture*>(texture)->deleteTexture(); 13538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck delete texture; 13638e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck } 13738e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck} 13838e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck 13938e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck} // namespace uirenderer 14038e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck} // namespace android; 141