1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2023 Google LLC 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker #ifndef skgpu_graphite_AtlasProvider_DEFINED 9*c8dee2aaSAndroid Build Coastguard Worker #define skgpu_graphite_AtlasProvider_DEFINED 10*c8dee2aaSAndroid Build Coastguard Worker 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorType.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTo.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkEnumBitMask.h" 15*c8dee2aaSAndroid Build Coastguard Worker 16*c8dee2aaSAndroid Build Coastguard Worker #include <memory> 17*c8dee2aaSAndroid Build Coastguard Worker #include <unordered_map> 18*c8dee2aaSAndroid Build Coastguard Worker 19*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu::graphite { 20*c8dee2aaSAndroid Build Coastguard Worker 21*c8dee2aaSAndroid Build Coastguard Worker class Caps; 22*c8dee2aaSAndroid Build Coastguard Worker class ComputePathAtlas; 23*c8dee2aaSAndroid Build Coastguard Worker class DrawContext; 24*c8dee2aaSAndroid Build Coastguard Worker class PathAtlas; 25*c8dee2aaSAndroid Build Coastguard Worker class RasterPathAtlas; 26*c8dee2aaSAndroid Build Coastguard Worker class Recorder; 27*c8dee2aaSAndroid Build Coastguard Worker class TextAtlasManager; 28*c8dee2aaSAndroid Build Coastguard Worker class TextureProxy; 29*c8dee2aaSAndroid Build Coastguard Worker 30*c8dee2aaSAndroid Build Coastguard Worker /** 31*c8dee2aaSAndroid Build Coastguard Worker * AtlasProvider groups various texture atlas management algorithms together. 32*c8dee2aaSAndroid Build Coastguard Worker */ 33*c8dee2aaSAndroid Build Coastguard Worker class AtlasProvider final { 34*c8dee2aaSAndroid Build Coastguard Worker public: 35*c8dee2aaSAndroid Build Coastguard Worker enum class PathAtlasFlags : unsigned { 36*c8dee2aaSAndroid Build Coastguard Worker kNone = 0b000, 37*c8dee2aaSAndroid Build Coastguard Worker // ComputePathAtlas is supported 38*c8dee2aaSAndroid Build Coastguard Worker kCompute = 0b001, 39*c8dee2aaSAndroid Build Coastguard Worker // RasterPathAtlas is supported 40*c8dee2aaSAndroid Build Coastguard Worker kRaster = 0b010, 41*c8dee2aaSAndroid Build Coastguard Worker }; 42*c8dee2aaSAndroid Build Coastguard Worker SK_DECL_BITMASK_OPS_FRIENDS(PathAtlasFlags) 43*c8dee2aaSAndroid Build Coastguard Worker using PathAtlasFlagsBitMask = SkEnumBitMask<PathAtlasFlags>; 44*c8dee2aaSAndroid Build Coastguard Worker 45*c8dee2aaSAndroid Build Coastguard Worker // Query the supported path atlas algorithms based on device capabilities. 46*c8dee2aaSAndroid Build Coastguard Worker static PathAtlasFlagsBitMask QueryPathAtlasSupport(const Caps*); 47*c8dee2aaSAndroid Build Coastguard Worker 48*c8dee2aaSAndroid Build Coastguard Worker explicit AtlasProvider(Recorder*); 49*c8dee2aaSAndroid Build Coastguard Worker ~AtlasProvider() = default; 50*c8dee2aaSAndroid Build Coastguard Worker 51*c8dee2aaSAndroid Build Coastguard Worker // Returns the TextAtlasManager that provides access to persistent DrawAtlas instances used in 52*c8dee2aaSAndroid Build Coastguard Worker // glyph rendering. This TextAtlasManager is always available. textAtlasManager()53*c8dee2aaSAndroid Build Coastguard Worker TextAtlasManager* textAtlasManager() const { return fTextAtlasManager.get(); } 54*c8dee2aaSAndroid Build Coastguard Worker 55*c8dee2aaSAndroid Build Coastguard Worker // Returns whether a particular atlas type is available. Currently PathAtlasFlags::kRaster is 56*c8dee2aaSAndroid Build Coastguard Worker // always supported. isAvailable(PathAtlasFlags atlasType)57*c8dee2aaSAndroid Build Coastguard Worker bool isAvailable(PathAtlasFlags atlasType) const { 58*c8dee2aaSAndroid Build Coastguard Worker return SkToBool(fPathAtlasFlags & atlasType); 59*c8dee2aaSAndroid Build Coastguard Worker } 60*c8dee2aaSAndroid Build Coastguard Worker 61*c8dee2aaSAndroid Build Coastguard Worker // Creates a new transient atlas handler that uses compute shaders to rasterize coverage masks 62*c8dee2aaSAndroid Build Coastguard Worker // for path rendering. This method returns nullptr if compute shaders are not supported by the 63*c8dee2aaSAndroid Build Coastguard Worker // owning Recorder's context. 64*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<ComputePathAtlas> createComputePathAtlas(Recorder* recorder) const; 65*c8dee2aaSAndroid Build Coastguard Worker 66*c8dee2aaSAndroid Build Coastguard Worker // Gets the atlas handler that uses the CPU raster pipeline to create coverage masks 67*c8dee2aaSAndroid Build Coastguard Worker // for path rendering. 68*c8dee2aaSAndroid Build Coastguard Worker RasterPathAtlas* getRasterPathAtlas() const; 69*c8dee2aaSAndroid Build Coastguard Worker 70*c8dee2aaSAndroid Build Coastguard Worker // Return a TextureProxy with the given dimensions and color type. 71*c8dee2aaSAndroid Build Coastguard Worker sk_sp<TextureProxy> getAtlasTexture( 72*c8dee2aaSAndroid Build Coastguard Worker Recorder*, uint16_t width, uint16_t height, SkColorType, uint16_t identifier, 73*c8dee2aaSAndroid Build Coastguard Worker bool requireStorageUsage); 74*c8dee2aaSAndroid Build Coastguard Worker 75*c8dee2aaSAndroid Build Coastguard Worker // This frees textures held in the atlas pool, and compacts the pages within the other 76*c8dee2aaSAndroid Build Coastguard Worker // atlas managers. It does not free resources that are in use or clear cached masks. 77*c8dee2aaSAndroid Build Coastguard Worker void freeGpuResources(); 78*c8dee2aaSAndroid Build Coastguard Worker 79*c8dee2aaSAndroid Build Coastguard Worker // Push any pending uploads to atlases onto the draw context 80*c8dee2aaSAndroid Build Coastguard Worker void recordUploads(DrawContext*); 81*c8dee2aaSAndroid Build Coastguard Worker 82*c8dee2aaSAndroid Build Coastguard Worker // Handle any post-flush work (garbage collection) 83*c8dee2aaSAndroid Build Coastguard Worker void compact(bool forceCompact); 84*c8dee2aaSAndroid Build Coastguard Worker 85*c8dee2aaSAndroid Build Coastguard Worker // Invalidate any cached state about what may or may not already be uploaded in the atlas. 86*c8dee2aaSAndroid Build Coastguard Worker void invalidateAtlases(); 87*c8dee2aaSAndroid Build Coastguard Worker 88*c8dee2aaSAndroid Build Coastguard Worker private: 89*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<TextAtlasManager> fTextAtlasManager; 90*c8dee2aaSAndroid Build Coastguard Worker 91*c8dee2aaSAndroid Build Coastguard Worker // Accumulates atlas coverage masks generated by software rendering that are required by one or 92*c8dee2aaSAndroid Build Coastguard Worker // more entries in `fPendingDraws`. During the snapUploadTask step, prior to pending draws 93*c8dee2aaSAndroid Build Coastguard Worker // being snapped into a new DrawPass, any necessary uploads into an atlas texture are recorded 94*c8dee2aaSAndroid Build Coastguard Worker // for the accumulated masks. The accumulated masks are then cleared which frees up the atlas 95*c8dee2aaSAndroid Build Coastguard Worker // for future draws. 96*c8dee2aaSAndroid Build Coastguard Worker // 97*c8dee2aaSAndroid Build Coastguard Worker // TODO: We should not clear all accumulated masks but cache masks over more than one frame. 98*c8dee2aaSAndroid Build Coastguard Worker // 99*c8dee2aaSAndroid Build Coastguard Worker // TODO: We may need a method to generate raster-generated masks in separate threads prior to 100*c8dee2aaSAndroid Build Coastguard Worker // upload. 101*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<RasterPathAtlas> fRasterPathAtlas; 102*c8dee2aaSAndroid Build Coastguard Worker 103*c8dee2aaSAndroid Build Coastguard Worker // Allocated and cached texture proxies shared by all PathAtlas instances. It is possible for 104*c8dee2aaSAndroid Build Coastguard Worker // the same texture to be bound to multiple DispatchGroups and DrawPasses across flushes. The 105*c8dee2aaSAndroid Build Coastguard Worker // owning Recorder must guarantee that any uploads or compute dispatches are scheduled to remain 106*c8dee2aaSAndroid Build Coastguard Worker // coherent across flushes. 107*c8dee2aaSAndroid Build Coastguard Worker // TODO: This requirement might change with a more sophisticated reuse scheme for texture 108*c8dee2aaSAndroid Build Coastguard Worker // allocations. For now our model is simple: all PathAtlases target the same texture and only 109*c8dee2aaSAndroid Build Coastguard Worker // one of them will render to the texture during a given command submission. 110*c8dee2aaSAndroid Build Coastguard Worker std::unordered_map<uint64_t, sk_sp<TextureProxy>> fTexturePool; 111*c8dee2aaSAndroid Build Coastguard Worker 112*c8dee2aaSAndroid Build Coastguard Worker PathAtlasFlagsBitMask fPathAtlasFlags = PathAtlasFlags::kNone; 113*c8dee2aaSAndroid Build Coastguard Worker }; 114*c8dee2aaSAndroid Build Coastguard Worker 115*c8dee2aaSAndroid Build Coastguard Worker SK_MAKE_BITMASK_OPS(AtlasProvider::PathAtlasFlags) 116*c8dee2aaSAndroid Build Coastguard Worker 117*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu::graphite 118*c8dee2aaSAndroid Build Coastguard Worker 119*c8dee2aaSAndroid Build Coastguard Worker #endif // skgpu_graphite_AtlasProvider_DEFINED 120