Coverage Report

Created: 2024-09-14 07:19

/src/skia/src/gpu/graphite/CommandBuffer.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2021 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
#include "src/gpu/graphite/CommandBuffer.h"
9
10
#include "src/core/SkTraceEvent.h"
11
#include "src/gpu/RefCntedCallback.h"
12
#include "src/gpu/graphite/Buffer.h"
13
#include "src/gpu/graphite/ComputePipeline.h"
14
#include "src/gpu/graphite/DrawPass.h"
15
#include "src/gpu/graphite/GraphicsPipeline.h"
16
#include "src/gpu/graphite/Log.h"
17
#include "src/gpu/graphite/RenderPassDesc.h"
18
#include "src/gpu/graphite/ResourceProvider.h"
19
#include "src/gpu/graphite/Sampler.h"
20
#include "src/gpu/graphite/Texture.h"
21
#include "src/gpu/graphite/TextureProxy.h"
22
23
namespace skgpu::graphite {
24
25
0
CommandBuffer::CommandBuffer() {}
26
27
0
CommandBuffer::~CommandBuffer() {
28
0
    this->releaseResources();
29
0
}
30
31
0
void CommandBuffer::releaseResources() {
32
0
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
33
34
0
    fTrackedUsageResources.clear();
35
0
    fCommandBufferResources.clear();
36
0
}
37
38
0
void CommandBuffer::resetCommandBuffer() {
39
0
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
40
41
0
    this->releaseResources();
42
0
    this->onResetCommandBuffer();
43
0
    fBuffersToAsyncMap.clear();
44
0
}
45
46
0
void CommandBuffer::trackResource(sk_sp<Resource> resource) {
47
0
    fTrackedUsageResources.push_back(std::move(resource));
48
0
}
49
50
0
void CommandBuffer::trackCommandBufferResource(sk_sp<Resource> resource) {
51
0
    fCommandBufferResources.push_back(std::move(resource));
52
0
}
53
54
0
void CommandBuffer::addFinishedProc(sk_sp<RefCntedCallback> finishedProc) {
55
0
    fFinishedProcs.push_back(std::move(finishedProc));
56
0
}
57
58
0
void CommandBuffer::callFinishedProcs(bool success) {
59
0
    if (!success) {
60
0
        for (int i = 0; i < fFinishedProcs.size(); ++i) {
61
0
            fFinishedProcs[i]->setFailureResult();
62
0
        }
63
0
    }
64
0
    fFinishedProcs.clear();
65
0
}
66
67
0
void CommandBuffer::addBuffersToAsyncMapOnSubmit(SkSpan<const sk_sp<Buffer>> buffers) {
68
0
    for (size_t i = 0; i < buffers.size(); ++i) {
69
0
        SkASSERT(buffers[i]);
70
0
        fBuffersToAsyncMap.push_back(buffers[i]);
71
0
    }
72
0
}
Unexecuted instantiation: skgpu::graphite::CommandBuffer::addBuffersToAsyncMapOnSubmit(SkSpan<sk_sp<skgpu::graphite::Buffer> const>)
Unexecuted instantiation: skgpu::graphite::CommandBuffer::addBuffersToAsyncMapOnSubmit(SkSpan<sk_sp<skgpu::graphite::Buffer> const>)
73
74
0
SkSpan<const sk_sp<Buffer>> CommandBuffer::buffersToAsyncMapOnSubmit() const {
75
0
    return fBuffersToAsyncMap;
76
0
}
77
78
bool CommandBuffer::addRenderPass(const RenderPassDesc& renderPassDesc,
79
                                  sk_sp<Texture> colorTexture,
80
                                  sk_sp<Texture> resolveTexture,
81
                                  sk_sp<Texture> depthStencilTexture,
82
                                  const Texture* dstCopy,
83
                                  SkIRect dstCopyBounds,
84
                                  SkIRect viewport,
85
0
                                  const DrawPassList& drawPasses) {
86
0
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
87
88
0
    fColorAttachmentSize = colorTexture->dimensions();
89
0
    SkIRect colorAttachmentBounds = SkIRect::MakeSize(fColorAttachmentSize);
90
91
0
    SkIRect renderPassBounds;
92
0
    for (const auto& drawPass : drawPasses) {
93
0
        renderPassBounds.join(drawPass->bounds());
94
0
    }
95
0
    if (renderPassDesc.fColorAttachment.fLoadOp == LoadOp::kClear) {
96
0
        renderPassBounds.join(colorAttachmentBounds);
97
0
    }
98
0
    renderPassBounds.offset(fReplayTranslation.x(), fReplayTranslation.y());
99
0
    if (!renderPassBounds.intersect(colorAttachmentBounds)) {
100
        // The entire RenderPass is offscreen given the replay translation so skip adding the pass
101
        // at all
102
0
        return true;
103
0
    }
104
105
0
    viewport.offset(fReplayTranslation.x(), fReplayTranslation.y());
106
107
0
    dstCopyBounds.offset(fReplayTranslation.x(), fReplayTranslation.y());
108
0
    if (!dstCopyBounds.intersect(colorAttachmentBounds)) {
109
        // The draws within the RenderPass that would sample from the dstCopy have been translated
110
        // off screen. Set the bounds to empty and let the GPU clipping do its job.
111
0
        dstCopyBounds = SkIRect::MakeEmpty();
112
0
    }
113
    // Save the dstCopy texture so that it can be embedded into texture bind commands later on.
114
0
    fDstCopy.first = dstCopy;
115
0
    fDstCopyOffset = dstCopyBounds.topLeft();
116
0
    if (dstCopy && !fDstCopy.second) {
117
        // Only lookup the sampler the first time we require a dstCopy. The texture can change
118
        // on subsequent passes but it will always use the same nearest neighbor sampling.
119
0
        sk_sp<Sampler> nearestNeighbor = this->resourceProvider()->findOrCreateCompatibleSampler(
120
0
                {SkFilterMode::kNearest, SkTileMode::kClamp});
121
0
        fDstCopy.second = nearestNeighbor.get();
122
0
        this->trackResource(std::move(nearestNeighbor));
123
0
    }
124
125
0
    if (!this->onAddRenderPass(renderPassDesc,
126
0
                               renderPassBounds,
127
0
                               colorTexture.get(),
128
0
                               resolveTexture.get(),
129
0
                               depthStencilTexture.get(),
130
0
                               viewport,
131
0
                               drawPasses)) {
132
0
        return false;
133
0
    }
134
135
0
    if (colorTexture) {
136
0
        this->trackCommandBufferResource(std::move(colorTexture));
137
0
    }
138
0
    if (resolveTexture) {
139
0
        this->trackCommandBufferResource(std::move(resolveTexture));
140
0
    }
141
0
    if (depthStencilTexture) {
142
0
        this->trackCommandBufferResource(std::move(depthStencilTexture));
143
0
    }
144
    // We just assume if you are adding a render pass that the render pass will actually do work. In
145
    // theory we could have a discard load that doesn't submit any draws, clears, etc. But hopefully
146
    // something so trivial would be caught before getting here.
147
0
    SkDEBUGCODE(fHasWork = true;)
148
149
0
    return true;
150
0
}
Unexecuted instantiation: skgpu::graphite::CommandBuffer::addRenderPass(skgpu::graphite::RenderPassDesc const&, sk_sp<skgpu::graphite::Texture>, sk_sp<skgpu::graphite::Texture>, sk_sp<skgpu::graphite::Texture>, skgpu::graphite::Texture const*, SkIRect, SkIRect, skia_private::TArray<std::__1::unique_ptr<skgpu::graphite::DrawPass, std::__1::default_delete<skgpu::graphite::DrawPass> >, true> const&)
Unexecuted instantiation: skgpu::graphite::CommandBuffer::addRenderPass(skgpu::graphite::RenderPassDesc const&, sk_sp<skgpu::graphite::Texture>, sk_sp<skgpu::graphite::Texture>, sk_sp<skgpu::graphite::Texture>, skgpu::graphite::Texture const*, SkIRect, SkIRect, skia_private::TArray<std::__1::unique_ptr<skgpu::graphite::DrawPass, std::__1::default_delete<skgpu::graphite::DrawPass> >, true> const&)
151
152
0
bool CommandBuffer::addComputePass(DispatchGroupSpan dispatchGroups) {
153
0
    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
154
155
0
    if (!this->onAddComputePass(dispatchGroups)) {
156
0
        return false;
157
0
    }
158
159
0
    SkDEBUGCODE(fHasWork = true;)
160
161
0
    return true;
162
0
}
Unexecuted instantiation: skgpu::graphite::CommandBuffer::addComputePass(SkSpan<std::__1::unique_ptr<skgpu::graphite::DispatchGroup, std::__1::default_delete<skgpu::graphite::DispatchGroup> > const>)
Unexecuted instantiation: skgpu::graphite::CommandBuffer::addComputePass(SkSpan<std::__1::unique_ptr<skgpu::graphite::DispatchGroup, std::__1::default_delete<skgpu::graphite::DispatchGroup> > const>)
163
164
bool CommandBuffer::copyBufferToBuffer(const Buffer* srcBuffer,
165
                                       size_t srcOffset,
166
                                       sk_sp<Buffer> dstBuffer,
167
                                       size_t dstOffset,
168
0
                                       size_t size) {
169
0
    SkASSERT(srcBuffer);
170
0
    SkASSERT(dstBuffer);
171
172
0
    if (!this->onCopyBufferToBuffer(srcBuffer, srcOffset, dstBuffer.get(), dstOffset, size)) {
173
0
        return false;
174
0
    }
175
176
0
    this->trackResource(std::move(dstBuffer));
177
178
0
    SkDEBUGCODE(fHasWork = true;)
179
180
0
    return true;
181
0
}
Unexecuted instantiation: skgpu::graphite::CommandBuffer::copyBufferToBuffer(skgpu::graphite::Buffer const*, unsigned long, sk_sp<skgpu::graphite::Buffer>, unsigned long, unsigned long)
Unexecuted instantiation: skgpu::graphite::CommandBuffer::copyBufferToBuffer(skgpu::graphite::Buffer const*, unsigned long, sk_sp<skgpu::graphite::Buffer>, unsigned long, unsigned long)
182
183
bool CommandBuffer::copyTextureToBuffer(sk_sp<Texture> texture,
184
                                        SkIRect srcRect,
185
                                        sk_sp<Buffer> buffer,
186
                                        size_t bufferOffset,
187
0
                                        size_t bufferRowBytes) {
188
0
    SkASSERT(texture);
189
0
    SkASSERT(buffer);
190
191
0
    if (!this->onCopyTextureToBuffer(texture.get(), srcRect, buffer.get(), bufferOffset,
192
0
                                     bufferRowBytes)) {
193
0
        return false;
194
0
    }
195
196
0
    this->trackCommandBufferResource(std::move(texture));
197
0
    this->trackResource(std::move(buffer));
198
199
0
    SkDEBUGCODE(fHasWork = true;)
200
201
0
    return true;
202
0
}
Unexecuted instantiation: skgpu::graphite::CommandBuffer::copyTextureToBuffer(sk_sp<skgpu::graphite::Texture>, SkIRect, sk_sp<skgpu::graphite::Buffer>, unsigned long, unsigned long)
Unexecuted instantiation: skgpu::graphite::CommandBuffer::copyTextureToBuffer(sk_sp<skgpu::graphite::Texture>, SkIRect, sk_sp<skgpu::graphite::Buffer>, unsigned long, unsigned long)
203
204
bool CommandBuffer::copyBufferToTexture(const Buffer* buffer,
205
                                        sk_sp<Texture> texture,
206
                                        const BufferTextureCopyData* copyData,
207
0
                                        int count) {
208
0
    SkASSERT(buffer);
209
0
    SkASSERT(texture);
210
0
    SkASSERT(count > 0 && copyData);
211
212
0
    if (!this->onCopyBufferToTexture(buffer, texture.get(), copyData, count)) {
213
0
        return false;
214
0
    }
215
216
0
    this->trackCommandBufferResource(std::move(texture));
217
218
0
    SkDEBUGCODE(fHasWork = true;)
219
220
0
    return true;
221
0
}
Unexecuted instantiation: skgpu::graphite::CommandBuffer::copyBufferToTexture(skgpu::graphite::Buffer const*, sk_sp<skgpu::graphite::Texture>, skgpu::graphite::BufferTextureCopyData const*, int)
Unexecuted instantiation: skgpu::graphite::CommandBuffer::copyBufferToTexture(skgpu::graphite::Buffer const*, sk_sp<skgpu::graphite::Texture>, skgpu::graphite::BufferTextureCopyData const*, int)
222
223
bool CommandBuffer::copyTextureToTexture(sk_sp<Texture> src,
224
                                         SkIRect srcRect,
225
                                         sk_sp<Texture> dst,
226
                                         SkIPoint dstPoint,
227
0
                                         int mipLevel) {
228
0
    SkASSERT(src);
229
0
    SkASSERT(dst);
230
0
    if (src->textureInfo().isProtected() == Protected::kYes &&
231
0
        dst->textureInfo().isProtected() != Protected::kYes) {
232
0
        SKGPU_LOG_E("Can't copy from protected memory to non-protected");
233
0
        return false;
234
0
    }
235
236
0
    if (!this->onCopyTextureToTexture(src.get(), srcRect, dst.get(), dstPoint, mipLevel)) {
237
0
        return false;
238
0
    }
239
240
0
    this->trackCommandBufferResource(std::move(src));
241
0
    this->trackCommandBufferResource(std::move(dst));
242
243
0
    SkDEBUGCODE(fHasWork = true;)
244
245
0
    return true;
246
0
}
Unexecuted instantiation: skgpu::graphite::CommandBuffer::copyTextureToTexture(sk_sp<skgpu::graphite::Texture>, SkIRect, sk_sp<skgpu::graphite::Texture>, SkIPoint, int)
Unexecuted instantiation: skgpu::graphite::CommandBuffer::copyTextureToTexture(sk_sp<skgpu::graphite::Texture>, SkIRect, sk_sp<skgpu::graphite::Texture>, SkIPoint, int)
247
248
0
bool CommandBuffer::synchronizeBufferToCpu(sk_sp<Buffer> buffer) {
249
0
    SkASSERT(buffer);
250
251
0
    bool didResultInWork = false;
252
0
    if (!this->onSynchronizeBufferToCpu(buffer.get(), &didResultInWork)) {
253
0
        return false;
254
0
    }
255
256
0
    if (didResultInWork) {
257
0
        this->trackResource(std::move(buffer));
258
0
        SkDEBUGCODE(fHasWork = true;)
259
0
    }
260
261
0
    return true;
262
0
}
Unexecuted instantiation: skgpu::graphite::CommandBuffer::synchronizeBufferToCpu(sk_sp<skgpu::graphite::Buffer>)
Unexecuted instantiation: skgpu::graphite::CommandBuffer::synchronizeBufferToCpu(sk_sp<skgpu::graphite::Buffer>)
263
264
0
bool CommandBuffer::clearBuffer(const Buffer* buffer, size_t offset, size_t size) {
265
0
    SkASSERT(buffer);
266
267
0
    if (!this->onClearBuffer(buffer, offset, size)) {
268
0
        return false;
269
0
    }
270
271
0
    SkDEBUGCODE(fHasWork = true;)
272
273
0
    return true;
274
0
}
Unexecuted instantiation: skgpu::graphite::CommandBuffer::clearBuffer(skgpu::graphite::Buffer const*, unsigned long, unsigned long)
Unexecuted instantiation: skgpu::graphite::CommandBuffer::clearBuffer(skgpu::graphite::Buffer const*, unsigned long, unsigned long)
275
276
} // namespace skgpu::graphite