/* * Copyright 2017 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef GrResourceAllocator_DEFINED #define GrResourceAllocator_DEFINED #include "include/core/SkRefCnt.h" #include "include/private/base/SkAssert.h" #include "include/private/base/SkDebug.h" #include "include/private/base/SkTo.h" #include "src/base/SkArenaAlloc.h" #include "src/core/SkTHash.h" #include "src/core/SkTMultiMap.h" #include "src/gpu/ResourceKey.h" #include "src/gpu/ganesh/GrCaps.h" #include "src/gpu/ganesh/GrHashMapWithCache.h" #include "src/gpu/ganesh/GrSurface.h" #include "src/gpu/ganesh/GrSurfaceProxy.h" #include <cstdint> class GrDirectContext; class GrResourceProvider; // Print out explicit allocation information #define GR_ALLOCATION_SPEW … // Print out information about interval creation #define GR_TRACK_INTERVAL_CREATION … /* * The ResourceAllocator explicitly distributes GPU resources at flush time. It operates by * being given the usage intervals of the various proxies. It keeps these intervals in a singly * linked list sorted by increasing start index. (It also maintains a hash table from proxyID * to interval to find proxy reuse). The ResourceAllocator uses Registers (in the sense of register * allocation) to represent a future surface that will be used for each proxy during * `planAssignment`, and then assigns actual surfaces during `assign`. * * Note: the op indices (used in the usage intervals) come from the order of the ops in * their opsTasks after the opsTask DAG has been linearized. * * The planAssignment method traverses the sorted list and: * moves intervals from the active list that have completed (returning their registers * to the free pool) into the finished list (sorted by increasing start) * * allocates a new register (preferably from the free pool) for the new interval * adds the new interval to the active list (that is sorted by increasing end index) * * After assignment planning, the user can choose to call `makeBudgetHeadroom` which: * computes how much VRAM would be needed for new resources for all extant Registers * * asks the resource cache to purge enough resources to get that much free space * * if it's not possible, do nothing and return false. The user may opt to reset * the allocator and start over with a different DAG. * * If the user wants to commit to the current assignment plan, they call `assign` which: * instantiates lazy proxies * * instantantiates new surfaces for all registers that need them * * assigns the surface for each register to all the proxies that will use it * ************************************************************************************************* * How does instantiation failure handling work when explicitly allocating? * * In the gather usage intervals pass all the GrSurfaceProxies used in the flush should be * gathered (i.e., in OpsTask::gatherProxyIntervals). * * During addInterval, read-only lazy proxies are instantiated. If that fails, the resource * allocator will note the failure and ignore pretty much anything else until `reset`. * * During planAssignment, fully-lazy proxies are instantiated so that we can know their size for * budgeting purposes. If this fails, return false. * * During assign, partially-lazy proxies are instantiated and new surfaces are created for all other * proxies. If any of these fails, return false. * * The drawing manager will drop the flush if any proxies fail to instantiate. */ class GrResourceAllocator { … }; #endif // GrResourceAllocator_DEFINED