/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 |