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/GraphicsPipeline.h"
15 #include "src/gpu/graphite/Log.h"
16 #include "src/gpu/graphite/Sampler.h"
17 #include "src/gpu/graphite/Texture.h"
18 #include "src/gpu/graphite/TextureProxy.h"
19
20 namespace skgpu::graphite {
21
CommandBuffer()22 CommandBuffer::CommandBuffer() {}
23
~CommandBuffer()24 CommandBuffer::~CommandBuffer() {
25 this->releaseResources();
26 }
27
releaseResources()28 void CommandBuffer::releaseResources() {
29 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
30
31 fTrackedUsageResources.clear();
32 fCommandBufferResources.clear();
33 }
34
resetCommandBuffer()35 void CommandBuffer::resetCommandBuffer() {
36 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
37
38 this->releaseResources();
39 this->onResetCommandBuffer();
40 fBuffersToAsyncMap.clear();
41 }
42
trackResource(sk_sp<Resource> resource)43 void CommandBuffer::trackResource(sk_sp<Resource> resource) {
44 fTrackedUsageResources.push_back(std::move(resource));
45 }
46
trackCommandBufferResource(sk_sp<Resource> resource)47 void CommandBuffer::trackCommandBufferResource(sk_sp<Resource> resource) {
48 fCommandBufferResources.push_back(std::move(resource));
49 }
50
addFinishedProc(sk_sp<RefCntedCallback> finishedProc)51 void CommandBuffer::addFinishedProc(sk_sp<RefCntedCallback> finishedProc) {
52 fFinishedProcs.push_back(std::move(finishedProc));
53 }
54
callFinishedProcs(bool success)55 void CommandBuffer::callFinishedProcs(bool success) {
56 if (!success) {
57 for (int i = 0; i < fFinishedProcs.size(); ++i) {
58 fFinishedProcs[i]->setFailureResult();
59 }
60 }
61 fFinishedProcs.clear();
62 }
63
addBuffersToAsyncMapOnSubmit(SkSpan<const sk_sp<Buffer>> buffers)64 void CommandBuffer::addBuffersToAsyncMapOnSubmit(SkSpan<const sk_sp<Buffer>> buffers) {
65 for (size_t i = 0; i < buffers.size(); ++i) {
66 SkASSERT(buffers[i]);
67 fBuffersToAsyncMap.push_back(buffers[i]);
68 }
69 }
70
buffersToAsyncMapOnSubmit() const71 SkSpan<const sk_sp<Buffer>> CommandBuffer::buffersToAsyncMapOnSubmit() const {
72 return fBuffersToAsyncMap;
73 }
74
addRenderPass(const RenderPassDesc & renderPassDesc,sk_sp<Texture> colorTexture,sk_sp<Texture> resolveTexture,sk_sp<Texture> depthStencilTexture,SkRect viewport,const DrawPassList & drawPasses)75 bool CommandBuffer::addRenderPass(const RenderPassDesc& renderPassDesc,
76 sk_sp<Texture> colorTexture,
77 sk_sp<Texture> resolveTexture,
78 sk_sp<Texture> depthStencilTexture,
79 SkRect viewport,
80 const DrawPassList& drawPasses) {
81 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
82
83 fRenderPassSize = colorTexture->dimensions();
84 if (!this->onAddRenderPass(renderPassDesc,
85 colorTexture.get(),
86 resolveTexture.get(),
87 depthStencilTexture.get(),
88 viewport,
89 drawPasses)) {
90 return false;
91 }
92
93 if (colorTexture) {
94 this->trackCommandBufferResource(std::move(colorTexture));
95 }
96 if (resolveTexture) {
97 this->trackCommandBufferResource(std::move(resolveTexture));
98 }
99 if (depthStencilTexture) {
100 this->trackCommandBufferResource(std::move(depthStencilTexture));
101 }
102 // We just assume if you are adding a render pass that the render pass will actually do work. In
103 // theory we could have a discard load that doesn't submit any draws, clears, etc. But hopefully
104 // something so trivial would be caught before getting here.
105 SkDEBUGCODE(fHasWork = true;)
106
107 return true;
108 }
109
addComputePass(DispatchGroupSpan dispatchGroups)110 bool CommandBuffer::addComputePass(DispatchGroupSpan dispatchGroups) {
111 TRACE_EVENT0("skia.gpu", TRACE_FUNC);
112
113 if (!this->onAddComputePass(dispatchGroups)) {
114 return false;
115 }
116
117 SkDEBUGCODE(fHasWork = true;)
118
119 return true;
120 }
121
copyBufferToBuffer(const Buffer * srcBuffer,size_t srcOffset,sk_sp<Buffer> dstBuffer,size_t dstOffset,size_t size)122 bool CommandBuffer::copyBufferToBuffer(const Buffer* srcBuffer,
123 size_t srcOffset,
124 sk_sp<Buffer> dstBuffer,
125 size_t dstOffset,
126 size_t size) {
127 SkASSERT(srcBuffer);
128 SkASSERT(dstBuffer);
129
130 if (!this->onCopyBufferToBuffer(srcBuffer, srcOffset, dstBuffer.get(), dstOffset, size)) {
131 return false;
132 }
133
134 this->trackResource(std::move(dstBuffer));
135
136 SkDEBUGCODE(fHasWork = true;)
137
138 return true;
139 }
140
copyTextureToBuffer(sk_sp<Texture> texture,SkIRect srcRect,sk_sp<Buffer> buffer,size_t bufferOffset,size_t bufferRowBytes)141 bool CommandBuffer::copyTextureToBuffer(sk_sp<Texture> texture,
142 SkIRect srcRect,
143 sk_sp<Buffer> buffer,
144 size_t bufferOffset,
145 size_t bufferRowBytes) {
146 SkASSERT(texture);
147 SkASSERT(buffer);
148
149 if (!this->onCopyTextureToBuffer(texture.get(), srcRect, buffer.get(), bufferOffset,
150 bufferRowBytes)) {
151 return false;
152 }
153
154 this->trackCommandBufferResource(std::move(texture));
155 this->trackResource(std::move(buffer));
156
157 SkDEBUGCODE(fHasWork = true;)
158
159 return true;
160 }
161
copyBufferToTexture(const Buffer * buffer,sk_sp<Texture> texture,const BufferTextureCopyData * copyData,int count)162 bool CommandBuffer::copyBufferToTexture(const Buffer* buffer,
163 sk_sp<Texture> texture,
164 const BufferTextureCopyData* copyData,
165 int count) {
166 SkASSERT(buffer);
167 SkASSERT(texture);
168 SkASSERT(count > 0 && copyData);
169
170 if (!this->onCopyBufferToTexture(buffer, texture.get(), copyData, count)) {
171 return false;
172 }
173
174 this->trackCommandBufferResource(std::move(texture));
175
176 SkDEBUGCODE(fHasWork = true;)
177
178 return true;
179 }
180
copyTextureToTexture(sk_sp<Texture> src,SkIRect srcRect,sk_sp<Texture> dst,SkIPoint dstPoint,int mipLevel)181 bool CommandBuffer::copyTextureToTexture(sk_sp<Texture> src,
182 SkIRect srcRect,
183 sk_sp<Texture> dst,
184 SkIPoint dstPoint,
185 int mipLevel) {
186 SkASSERT(src);
187 SkASSERT(dst);
188 if (src->textureInfo().isProtected() == Protected::kYes &&
189 dst->textureInfo().isProtected() != Protected::kYes) {
190 SKGPU_LOG_E("Can't copy from protected memory to non-protected");
191 return false;
192 }
193
194 if (!this->onCopyTextureToTexture(src.get(), srcRect, dst.get(), dstPoint, mipLevel)) {
195 return false;
196 }
197
198 this->trackCommandBufferResource(std::move(src));
199 this->trackCommandBufferResource(std::move(dst));
200
201 SkDEBUGCODE(fHasWork = true;)
202
203 return true;
204 }
205
synchronizeBufferToCpu(sk_sp<Buffer> buffer)206 bool CommandBuffer::synchronizeBufferToCpu(sk_sp<Buffer> buffer) {
207 SkASSERT(buffer);
208
209 bool didResultInWork = false;
210 if (!this->onSynchronizeBufferToCpu(buffer.get(), &didResultInWork)) {
211 return false;
212 }
213
214 if (didResultInWork) {
215 this->trackResource(std::move(buffer));
216 SkDEBUGCODE(fHasWork = true;)
217 }
218
219 return true;
220 }
221
clearBuffer(const Buffer * buffer,size_t offset,size_t size)222 bool CommandBuffer::clearBuffer(const Buffer* buffer, size_t offset, size_t size) {
223 SkASSERT(buffer);
224
225 if (!this->onClearBuffer(buffer, offset, size)) {
226 return false;
227 }
228
229 SkDEBUGCODE(fHasWork = true;)
230
231 return true;
232 }
233
234 } // namespace skgpu::graphite
235