1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2022 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_task_UploadTask_DEFINED 9*c8dee2aaSAndroid Build Coastguard Worker #define skgpu_graphite_task_UploadTask_DEFINED 10*c8dee2aaSAndroid Build Coastguard Worker 11*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/task/Task.h" 12*c8dee2aaSAndroid Build Coastguard Worker 13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageInfo.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h" 16*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTArray.h" 17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/graphite/CommandTypes.h" 18*c8dee2aaSAndroid Build Coastguard Worker 19*c8dee2aaSAndroid Build Coastguard Worker #include <memory> 20*c8dee2aaSAndroid Build Coastguard Worker 21*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu::graphite { 22*c8dee2aaSAndroid Build Coastguard Worker 23*c8dee2aaSAndroid Build Coastguard Worker class Buffer; 24*c8dee2aaSAndroid Build Coastguard Worker class Recorder; 25*c8dee2aaSAndroid Build Coastguard Worker class TextureProxy; 26*c8dee2aaSAndroid Build Coastguard Worker 27*c8dee2aaSAndroid Build Coastguard Worker struct MipLevel { 28*c8dee2aaSAndroid Build Coastguard Worker const void* fPixels = nullptr; 29*c8dee2aaSAndroid Build Coastguard Worker size_t fRowBytes = 0; 30*c8dee2aaSAndroid Build Coastguard Worker }; 31*c8dee2aaSAndroid Build Coastguard Worker 32*c8dee2aaSAndroid Build Coastguard Worker /** 33*c8dee2aaSAndroid Build Coastguard Worker * The ConditionalUploadContext, if set, is used to determine whether an upload needs to occur 34*c8dee2aaSAndroid Build Coastguard Worker * on Recording playback. Clients will need to create their own subclasses to store the 35*c8dee2aaSAndroid Build Coastguard Worker * necessary data and override the needsUpload() method to do this check. 36*c8dee2aaSAndroid Build Coastguard Worker */ 37*c8dee2aaSAndroid Build Coastguard Worker class ConditionalUploadContext { 38*c8dee2aaSAndroid Build Coastguard Worker public: ~ConditionalUploadContext()39*c8dee2aaSAndroid Build Coastguard Worker virtual ~ConditionalUploadContext() {} 40*c8dee2aaSAndroid Build Coastguard Worker 41*c8dee2aaSAndroid Build Coastguard Worker // Return true if the upload needs to occur; false if it should be skipped this time. 42*c8dee2aaSAndroid Build Coastguard Worker virtual bool needsUpload(Context*) = 0; 43*c8dee2aaSAndroid Build Coastguard Worker 44*c8dee2aaSAndroid Build Coastguard Worker // Return true if the upload should be kept in the task (and possibly re-executed on replay 45*c8dee2aaSAndroid Build Coastguard Worker // depending on needsUpload()'s return value), or false if it should be discarded and never 46*c8dee2aaSAndroid Build Coastguard Worker // attempt to be uploaded on any replay. uploadSubmitted()47*c8dee2aaSAndroid Build Coastguard Worker virtual bool uploadSubmitted() { return true; } 48*c8dee2aaSAndroid Build Coastguard Worker }; 49*c8dee2aaSAndroid Build Coastguard Worker 50*c8dee2aaSAndroid Build Coastguard Worker /** 51*c8dee2aaSAndroid Build Coastguard Worker * ImageUploadContext is an implementation of ConditionalUploadContext that returns true on 52*c8dee2aaSAndroid Build Coastguard Worker * the first call to needsUpload() and then returns false on subsequent calls. This is used to 53*c8dee2aaSAndroid Build Coastguard Worker * upload an image once and then avoid redundant uploads after that. 54*c8dee2aaSAndroid Build Coastguard Worker */ 55*c8dee2aaSAndroid Build Coastguard Worker class ImageUploadContext : public ConditionalUploadContext { 56*c8dee2aaSAndroid Build Coastguard Worker public: ~ImageUploadContext()57*c8dee2aaSAndroid Build Coastguard Worker ~ImageUploadContext() override {} 58*c8dee2aaSAndroid Build Coastguard Worker 59*c8dee2aaSAndroid Build Coastguard Worker // Always upload, since it will be discarded right afterwards needsUpload(Context *)60*c8dee2aaSAndroid Build Coastguard Worker bool needsUpload(Context*) override { return true; } 61*c8dee2aaSAndroid Build Coastguard Worker 62*c8dee2aaSAndroid Build Coastguard Worker // Always return false so the upload instance is discarded after the first execution uploadSubmitted()63*c8dee2aaSAndroid Build Coastguard Worker bool uploadSubmitted() override { return false; } 64*c8dee2aaSAndroid Build Coastguard Worker }; 65*c8dee2aaSAndroid Build Coastguard Worker 66*c8dee2aaSAndroid Build Coastguard Worker /** 67*c8dee2aaSAndroid Build Coastguard Worker * An UploadInstance represents a single set of uploads from a buffer to texture that 68*c8dee2aaSAndroid Build Coastguard Worker * can be processed in a single command. 69*c8dee2aaSAndroid Build Coastguard Worker */ 70*c8dee2aaSAndroid Build Coastguard Worker class UploadInstance { 71*c8dee2aaSAndroid Build Coastguard Worker public: 72*c8dee2aaSAndroid Build Coastguard Worker static UploadInstance Make(Recorder*, 73*c8dee2aaSAndroid Build Coastguard Worker sk_sp<TextureProxy> targetProxy, 74*c8dee2aaSAndroid Build Coastguard Worker const SkColorInfo& srcColorInfo, 75*c8dee2aaSAndroid Build Coastguard Worker const SkColorInfo& dstColorInfo, 76*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const MipLevel> levels, 77*c8dee2aaSAndroid Build Coastguard Worker const SkIRect& dstRect, 78*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<ConditionalUploadContext>); 79*c8dee2aaSAndroid Build Coastguard Worker static UploadInstance MakeCompressed(Recorder*, 80*c8dee2aaSAndroid Build Coastguard Worker sk_sp<TextureProxy> targetProxy, 81*c8dee2aaSAndroid Build Coastguard Worker const void* data, 82*c8dee2aaSAndroid Build Coastguard Worker size_t dataSize); 83*c8dee2aaSAndroid Build Coastguard Worker Invalid()84*c8dee2aaSAndroid Build Coastguard Worker static UploadInstance Invalid() { return {}; } 85*c8dee2aaSAndroid Build Coastguard Worker 86*c8dee2aaSAndroid Build Coastguard Worker UploadInstance(UploadInstance&&); 87*c8dee2aaSAndroid Build Coastguard Worker UploadInstance& operator=(UploadInstance&&); 88*c8dee2aaSAndroid Build Coastguard Worker ~UploadInstance(); 89*c8dee2aaSAndroid Build Coastguard Worker isValid()90*c8dee2aaSAndroid Build Coastguard Worker bool isValid() const { return fBuffer != nullptr && fTextureProxy != nullptr; } 91*c8dee2aaSAndroid Build Coastguard Worker 92*c8dee2aaSAndroid Build Coastguard Worker bool prepareResources(ResourceProvider*); 93*c8dee2aaSAndroid Build Coastguard Worker 94*c8dee2aaSAndroid Build Coastguard Worker // Adds upload command to the given CommandBuffer, returns false if the instance should be 95*c8dee2aaSAndroid Build Coastguard Worker // discarded. 96*c8dee2aaSAndroid Build Coastguard Worker Task::Status addCommand(Context*, CommandBuffer*, Task::ReplayTargetData) const; 97*c8dee2aaSAndroid Build Coastguard Worker 98*c8dee2aaSAndroid Build Coastguard Worker private: 99*c8dee2aaSAndroid Build Coastguard Worker UploadInstance(); 100*c8dee2aaSAndroid Build Coastguard Worker // Copy data is appended directly after the object is created 101*c8dee2aaSAndroid Build Coastguard Worker UploadInstance(const Buffer*, 102*c8dee2aaSAndroid Build Coastguard Worker size_t bytesPerPixel, 103*c8dee2aaSAndroid Build Coastguard Worker sk_sp<TextureProxy>, 104*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<ConditionalUploadContext> = nullptr); 105*c8dee2aaSAndroid Build Coastguard Worker 106*c8dee2aaSAndroid Build Coastguard Worker const Buffer* fBuffer; 107*c8dee2aaSAndroid Build Coastguard Worker size_t fBytesPerPixel; 108*c8dee2aaSAndroid Build Coastguard Worker sk_sp<TextureProxy> fTextureProxy; 109*c8dee2aaSAndroid Build Coastguard Worker skia_private::STArray<1, BufferTextureCopyData> fCopyData; 110*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<ConditionalUploadContext> fConditionalContext; 111*c8dee2aaSAndroid Build Coastguard Worker }; 112*c8dee2aaSAndroid Build Coastguard Worker 113*c8dee2aaSAndroid Build Coastguard Worker /** 114*c8dee2aaSAndroid Build Coastguard Worker * An UploadList is a mutable collection of UploadCommands. 115*c8dee2aaSAndroid Build Coastguard Worker * 116*c8dee2aaSAndroid Build Coastguard Worker * Currently commands are accumulated in order and processed in the same order. Dependency 117*c8dee2aaSAndroid Build Coastguard Worker * management is expected to be handled by the TaskGraph. 118*c8dee2aaSAndroid Build Coastguard Worker * 119*c8dee2aaSAndroid Build Coastguard Worker * When an upload is appended to the list its data will be copied to a Buffer in 120*c8dee2aaSAndroid Build Coastguard Worker * preparation for a deferred upload. 121*c8dee2aaSAndroid Build Coastguard Worker */ 122*c8dee2aaSAndroid Build Coastguard Worker class UploadList { 123*c8dee2aaSAndroid Build Coastguard Worker public: 124*c8dee2aaSAndroid Build Coastguard Worker bool recordUpload(Recorder*, 125*c8dee2aaSAndroid Build Coastguard Worker sk_sp<TextureProxy> targetProxy, 126*c8dee2aaSAndroid Build Coastguard Worker const SkColorInfo& srcColorInfo, 127*c8dee2aaSAndroid Build Coastguard Worker const SkColorInfo& dstColorInfo, 128*c8dee2aaSAndroid Build Coastguard Worker SkSpan<const MipLevel> levels, 129*c8dee2aaSAndroid Build Coastguard Worker const SkIRect& dstRect, 130*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<ConditionalUploadContext>); 131*c8dee2aaSAndroid Build Coastguard Worker size()132*c8dee2aaSAndroid Build Coastguard Worker int size() { return fInstances.size(); } 133*c8dee2aaSAndroid Build Coastguard Worker 134*c8dee2aaSAndroid Build Coastguard Worker private: 135*c8dee2aaSAndroid Build Coastguard Worker friend class UploadTask; 136*c8dee2aaSAndroid Build Coastguard Worker 137*c8dee2aaSAndroid Build Coastguard Worker skia_private::STArray<1, UploadInstance> fInstances; 138*c8dee2aaSAndroid Build Coastguard Worker }; 139*c8dee2aaSAndroid Build Coastguard Worker 140*c8dee2aaSAndroid Build Coastguard Worker /* 141*c8dee2aaSAndroid Build Coastguard Worker * An UploadTask is a immutable collection of UploadCommands. 142*c8dee2aaSAndroid Build Coastguard Worker * 143*c8dee2aaSAndroid Build Coastguard Worker * When adding commands to the commandBuffer the texture proxies in those 144*c8dee2aaSAndroid Build Coastguard Worker * commands will be instantiated and the copy command added. 145*c8dee2aaSAndroid Build Coastguard Worker */ 146*c8dee2aaSAndroid Build Coastguard Worker class UploadTask final : public Task { 147*c8dee2aaSAndroid Build Coastguard Worker public: 148*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<UploadTask> Make(UploadList*); 149*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<UploadTask> Make(UploadInstance); 150*c8dee2aaSAndroid Build Coastguard Worker 151*c8dee2aaSAndroid Build Coastguard Worker ~UploadTask() override; 152*c8dee2aaSAndroid Build Coastguard Worker 153*c8dee2aaSAndroid Build Coastguard Worker Status prepareResources(ResourceProvider*, 154*c8dee2aaSAndroid Build Coastguard Worker ScratchResourceManager*, 155*c8dee2aaSAndroid Build Coastguard Worker const RuntimeEffectDictionary*) override; 156*c8dee2aaSAndroid Build Coastguard Worker 157*c8dee2aaSAndroid Build Coastguard Worker Status addCommands(Context*, CommandBuffer*, ReplayTargetData) override; 158*c8dee2aaSAndroid Build Coastguard Worker 159*c8dee2aaSAndroid Build Coastguard Worker private: 160*c8dee2aaSAndroid Build Coastguard Worker UploadTask(skia_private::TArray<UploadInstance>&&); 161*c8dee2aaSAndroid Build Coastguard Worker UploadTask(UploadInstance); 162*c8dee2aaSAndroid Build Coastguard Worker 163*c8dee2aaSAndroid Build Coastguard Worker skia_private::STArray<1, UploadInstance> fInstances; 164*c8dee2aaSAndroid Build Coastguard Worker }; 165*c8dee2aaSAndroid Build Coastguard Worker 166*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu::graphite 167*c8dee2aaSAndroid Build Coastguard Worker 168*c8dee2aaSAndroid Build Coastguard Worker #endif // skgpu_graphite_task_UploadTask_DEFINED 169