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