Flutter Engine
The Flutter Engine
GrD3DOpsRenderPass.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2020 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
9
23
24#ifdef SK_DEBUG
27#endif
28
29using namespace skia_private;
30
32
34 const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
36 const TArray<GrSurfaceProxy*, true>& sampledProxies) {
38 SkASSERT(fGpu == rt->getContext()->priv().getGpu());
39
40 this->INHERITED::set(rt, origin);
41
42 fBounds = bounds;
43
44 fColorLoadOp = colorInfo.fLoadOp;
45 fClearColor = colorInfo.fClearColor;
46 fStencilLoadOp = stencilInfo.fLoadOp;
47
48 // TODO
49
50 return true;
51}
52
54
55GrGpu* GrD3DOpsRenderPass::gpu() { return fGpu; }
56
57void GrD3DOpsRenderPass::onBegin() {
59 if (d3dRT->numSamples() > 1) {
60 d3dRT->msaaTextureResource()->setResourceState(fGpu, D3D12_RESOURCE_STATE_RENDER_TARGET);
61 } else {
62 d3dRT->setResourceState(fGpu, D3D12_RESOURCE_STATE_RENDER_TARGET);
63 }
64 fGpu->currentCommandList()->setRenderTarget(d3dRT);
65
66 if (GrLoadOp::kClear == fColorLoadOp) {
67 // Passing in nullptr for the rect clears the entire d3d RT. Is this correct? Does the load
68 // op respect the logical bounds of a RT?
69 fGpu->currentCommandList()->clearRenderTargetView(d3dRT, fClearColor, nullptr);
70 }
71
72 if (auto stencil = d3dRT->getStencilAttachment()) {
73 GrD3DAttachment* d3dStencil = static_cast<GrD3DAttachment*>(stencil);
74 d3dStencil->setResourceState(fGpu, D3D12_RESOURCE_STATE_DEPTH_WRITE);
75 if (fStencilLoadOp == GrLoadOp::kClear) {
76 fGpu->currentCommandList()->clearDepthStencilView(d3dStencil, 0, nullptr);
77 }
78 }
79}
80
82 GrStencilSettings stencilSettings = info.nonGLStencilSettings();
83 if (!stencilSettings.isDisabled()) {
84 unsigned int stencilRef = 0;
85 if (stencilSettings.isTwoSided()) {
86 SkASSERT(stencilSettings.postOriginCCWFace(info.origin()).fRef ==
87 stencilSettings.postOriginCWFace(info.origin()).fRef);
88 stencilRef = stencilSettings.postOriginCCWFace(info.origin()).fRef;
89 } else {
90 stencilRef = stencilSettings.singleSidedFace().fRef;
91 }
92 gpu->currentCommandList()->setStencilRef(stencilRef);
93 }
94}
95
97 const GrXferProcessor& xferProcessor = info.pipeline().getXferProcessor();
98 const skgpu::Swizzle& swizzle = info.pipeline().writeSwizzle();
99 const skgpu::BlendInfo& blendInfo = xferProcessor.getBlendInfo();
100 skgpu::BlendCoeff srcCoeff = blendInfo.fSrcBlend;
101 skgpu::BlendCoeff dstCoeff = blendInfo.fDstBlend;
102 float floatColors[4];
104 // Swizzle the blend to match what the shader will output.
105 SkPMColor4f blendConst = swizzle.applyTo(blendInfo.fBlendConstant);
106 floatColors[0] = blendConst.fR;
107 floatColors[1] = blendConst.fG;
108 floatColors[2] = blendConst.fB;
109 floatColors[3] = blendConst.fA;
110 } else {
111 memset(floatColors, 0, 4 * sizeof(float));
112 }
113 gpu->currentCommandList()->setBlendFactor(floatColors);
114}
115
117 D3D12_PRIMITIVE_TOPOLOGY topology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
118 switch (info.primitiveType()) {
120 topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
121 break;
123 topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
124 break;
126 topology = D3D_PRIMITIVE_TOPOLOGY_POINTLIST;
127 break;
129 topology = D3D_PRIMITIVE_TOPOLOGY_LINELIST;
130 break;
132 topology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
133 break;
134 default:
136 }
138}
139
140void set_scissor_rects(GrD3DGpu* gpu, const GrRenderTarget* renderTarget, GrSurfaceOrigin rtOrigin,
141 const SkIRect& scissorRect) {
142 SkASSERT(scissorRect.isEmpty() ||
143 SkIRect::MakeWH(renderTarget->width(), renderTarget->height()).contains(scissorRect));
144
145 D3D12_RECT scissor;
146 scissor.left = scissorRect.fLeft;
147 scissor.right = scissorRect.fRight;
148 if (kTopLeft_GrSurfaceOrigin == rtOrigin) {
149 scissor.top = scissorRect.fTop;
150 } else {
152 scissor.top = renderTarget->height() - scissorRect.fBottom;
153 }
154 scissor.bottom = scissor.top + scissorRect.height();
155
156 SkASSERT(scissor.left >= 0);
157 SkASSERT(scissor.top >= 0);
158 gpu->currentCommandList()->setScissorRects(1, &scissor);
159}
160
161void set_viewport(GrD3DGpu* gpu, const GrRenderTarget* renderTarget) {
162 D3D12_VIEWPORT viewport;
163 viewport.TopLeftX = 0.0f;
164 viewport.TopLeftY = 0.0f;
165 viewport.Width = SkIntToScalar(renderTarget->width());
166 viewport.Height = SkIntToScalar(renderTarget->height());
167 viewport.MinDepth = 0.0f;
168 viewport.MaxDepth = 1.0f;
169 gpu->currentCommandList()->setViewports(1, &viewport);
170}
171
172bool GrD3DOpsRenderPass::onBindPipeline(const GrProgramInfo& info, const SkRect& drawBounds) {
173 SkRect rtRect = SkRect::Make(fBounds);
174 if (rtRect.intersect(drawBounds)) {
175 rtRect.roundOut(&fCurrentPipelineBounds);
176 } else {
177 fCurrentPipelineBounds.setEmpty();
178 }
179
180 GrD3DRenderTarget* d3dRT = static_cast<GrD3DRenderTarget*>(fRenderTarget);
181 fCurrentPipelineState =
183 if (!fCurrentPipelineState) {
184 return false;
185 }
186
187 fGpu->currentCommandList()->setGraphicsRootSignature(fCurrentPipelineState->rootSignature());
188 fGpu->currentCommandList()->setPipelineState(fCurrentPipelineState->pipeline());
189 fCurrentPipelineState->setAndBindConstants(fGpu, fRenderTarget, info);
190
191 set_stencil_ref(fGpu, info);
192 set_blend_factor(fGpu, info);
194 if (!info.pipeline().isScissorTestEnabled()) {
195 // "Disable" scissor by setting it to the full pipeline bounds.
196 set_scissor_rects(fGpu, fRenderTarget, fOrigin, fCurrentPipelineBounds);
197 }
199
200 return true;
201}
202
203void GrD3DOpsRenderPass::onSetScissorRect(const SkIRect& scissor) {
204 SkIRect combinedScissorRect;
205 if (!combinedScissorRect.intersect(fCurrentPipelineBounds, scissor)) {
206 combinedScissorRect = SkIRect::MakeEmpty();
207 }
208
209 set_scissor_rects(fGpu, fRenderTarget, fOrigin, combinedScissorRect);
210}
211
213 SkASSERT(!tex->isProtected() || (rt->isProtected() && gpu->protectedContext()));
214 GrD3DTexture* d3dTex = static_cast<GrD3DTexture*>(tex);
215 SkASSERT(d3dTex);
216 d3dTex->setResourceState(gpu, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
217}
218
219bool GrD3DOpsRenderPass::onBindTextures(const GrGeometryProcessor& geomProc,
220 const GrSurfaceProxy* const geomProcTextures[],
221 const GrPipeline& pipeline) {
222 SkASSERT(fCurrentPipelineState);
223
224 // update textures to sampled resource state
225 for (int i = 0; i < geomProc.numTextureSamplers(); ++i) {
226 update_resource_state(geomProcTextures[i]->peekTexture(), fRenderTarget, fGpu);
227 }
228
229 pipeline.visitTextureEffects([&](const GrTextureEffect& te) {
231 });
232
233 if (GrTexture* dstTexture = pipeline.peekDstTexture()) {
234 update_resource_state(dstTexture, fRenderTarget, fGpu);
235 }
236
237 // TODO: possibly check for success once we start binding properly
238 fCurrentPipelineState->setAndBindTextures(fGpu, geomProc, geomProcTextures, pipeline);
239
240 return true;
241}
242
243void GrD3DOpsRenderPass::onBindBuffers(sk_sp<const GrBuffer> indexBuffer,
244 sk_sp<const GrBuffer> instanceBuffer,
245 sk_sp<const GrBuffer> vertexBuffer,
246 GrPrimitiveRestart primRestart) {
247 SkASSERT(GrPrimitiveRestart::kNo == primRestart);
248 SkASSERT(fCurrentPipelineState);
249 SkASSERT(!fGpu->caps()->usePrimitiveRestart()); // Ignore primitiveRestart parameter.
250
251 GrD3DDirectCommandList* currCmdList = fGpu->currentCommandList();
252 SkASSERT(currCmdList);
253
254 fCurrentPipelineState->bindBuffers(fGpu, std::move(indexBuffer), std::move(instanceBuffer),
255 std::move(vertexBuffer), currCmdList);
256}
257
258void GrD3DOpsRenderPass::onDrawInstanced(int instanceCount, int baseInstance, int vertexCount,
259 int baseVertex) {
260 SkASSERT(fCurrentPipelineState);
261 fGpu->currentCommandList()->drawInstanced(vertexCount, instanceCount, baseVertex, baseInstance);
262 fGpu->stats()->incNumDraws();
263}
264
265void GrD3DOpsRenderPass::onDrawIndexedInstanced(int indexCount, int baseIndex, int instanceCount,
266 int baseInstance, int baseVertex) {
267 SkASSERT(fCurrentPipelineState);
268 fGpu->currentCommandList()->drawIndexedInstanced(indexCount, instanceCount, baseIndex,
269 baseVertex, baseInstance);
270 fGpu->stats()->incNumDraws();
271}
272
273void GrD3DOpsRenderPass::onDrawIndirect(const GrBuffer* buffer, size_t offset, int drawCount) {
274 constexpr unsigned int kSlot = 0;
277 fGpu->currentCommandList()->executeIndirect(cmdSig, drawCount,
278 static_cast<const GrD3DBuffer*>(buffer), offset);
279 fGpu->stats()->incNumDraws();
280}
281
282void GrD3DOpsRenderPass::onDrawIndexedIndirect(const GrBuffer* buffer, size_t offset,
283 int drawCount) {
284 constexpr unsigned int kSlot = 0;
287 fGpu->currentCommandList()->executeIndirect(cmdSig, drawCount,
288 static_cast<const GrD3DBuffer*>(buffer), offset);
289 fGpu->stats()->incNumDraws();
290}
291
292
293static D3D12_RECT scissor_to_d3d_clear_rect(const GrScissorState& scissor,
294 const GrSurface* surface,
295 GrSurfaceOrigin origin) {
296 D3D12_RECT clearRect;
297 // Flip rect if necessary
298 SkIRect d3dRect;
299 if (!scissor.enabled()) {
300 d3dRect.setXYWH(0, 0, surface->width(), surface->height());
301 } else if (kBottomLeft_GrSurfaceOrigin != origin) {
302 d3dRect = scissor.rect();
303 } else {
304 d3dRect.setLTRB(scissor.rect().fLeft, surface->height() - scissor.rect().fBottom,
305 scissor.rect().fRight, surface->height() - scissor.rect().fTop);
306 }
307 clearRect.left = d3dRect.fLeft;
308 clearRect.right = d3dRect.fRight;
309 clearRect.top = d3dRect.fTop;
310 clearRect.bottom = d3dRect.fBottom;
311 return clearRect;
312}
313
314void GrD3DOpsRenderPass::onClear(const GrScissorState& scissor, std::array<float, 4> color) {
315 D3D12_RECT clearRect = scissor_to_d3d_clear_rect(scissor, fRenderTarget, fOrigin);
316 auto d3dRT = static_cast<GrD3DRenderTarget*>(fRenderTarget);
317 SkASSERT(d3dRT->grD3DResourceState()->getResourceState() == D3D12_RESOURCE_STATE_RENDER_TARGET);
318 fGpu->currentCommandList()->clearRenderTargetView(d3dRT, color, &clearRect);
319}
320
321void GrD3DOpsRenderPass::onClearStencilClip(const GrScissorState& scissor, bool insideStencilMask) {
323 // this should only be called internally when we know we have a
324 // stencil buffer.
325 SkASSERT(sb);
326 int stencilBitCount = GrBackendFormatStencilBits(sb->backendFormat());
327
328 // The contract with the callers does not guarantee that we preserve all bits in the stencil
329 // during this clear. Thus we will clear the entire stencil to the desired value.
330
331 uint8_t stencilColor = 0;
332 if (insideStencilMask) {
333 stencilColor = (1 << (stencilBitCount - 1));
334 }
335
336 D3D12_RECT clearRect = scissor_to_d3d_clear_rect(scissor, fRenderTarget, fOrigin);
337
338 auto d3dStencil = static_cast<GrD3DAttachment*>(sb);
339 fGpu->currentCommandList()->clearDepthStencilView(d3dStencil, stencilColor, &clearRect);
340}
341
343 // If we ever start using copy command lists for doing uploads, then we'll need to make sure
344 // we submit our main command list before doing the copy here and then start a new main command
345 // list.
346
347 fGpu->endRenderPass(fRenderTarget, fOrigin, fBounds);
348
349 // We pass in true here to signal that after the upload we need to set the upload texture's
350 // resource state back to D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE.
351 state->doUpload(upload, true);
352}
353
355 if (!fRenderTarget) {
356 return;
357 }
358
359 // We don't use render passes in d3d, so there is nothing to submit here as all commands have
360 // already been recorded on the main command list. If in the future we start to use render
361 // passes on d3d12 devices that support them (most likely ARM devices), then we
362 // will submit them here.
363 fGpu->endRenderPass(fRenderTarget, fOrigin, fBounds);
364}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
int GrBackendFormatStencilBits(const GrBackendFormat &format)
void set_blend_factor(GrD3DGpu *gpu, const GrProgramInfo &info)
void set_viewport(GrD3DGpu *gpu, const GrRenderTarget *renderTarget)
static D3D12_RECT scissor_to_d3d_clear_rect(const GrScissorState &scissor, const GrSurface *surface, GrSurfaceOrigin origin)
void set_scissor_rects(GrD3DGpu *gpu, const GrRenderTarget *renderTarget, GrSurfaceOrigin rtOrigin, const SkIRect &scissorRect)
void update_resource_state(GrTexture *tex, GrRenderTarget *rt, GrD3DGpu *gpu)
void set_primitive_topology(GrD3DGpu *gpu, const GrProgramInfo &info)
void set_stencil_ref(GrD3DGpu *gpu, const GrProgramInfo &info)
std::function< void(GrDeferredTextureUploadWritePixelsFn &)> GrDeferredTextureUploadFn
GrPrimitiveRestart
Definition: GrTypesPriv.h:56
GrSurfaceOrigin
Definition: GrTypes.h:147
@ kBottomLeft_GrSurfaceOrigin
Definition: GrTypes.h:149
@ kTopLeft_GrSurfaceOrigin
Definition: GrTypes.h:148
#define SkUNREACHABLE
Definition: SkAssert.h:135
#define SkASSERT(cond)
Definition: SkAssert.h:116
#define SkIntToScalar(x)
Definition: SkScalar.h:57
bool usePrimitiveRestart() const
Definition: GrCaps.h:112
void clearRenderTargetView(const GrD3DRenderTarget *renderTarget, std::array< float, 4 > color, const D3D12_RECT *rect)
void executeIndirect(const sk_sp< GrD3DCommandSignature > commandSig, unsigned int maxCommandCnt, const GrD3DBuffer *argumentBuffer, size_t argumentBufferOffset)
void setGraphicsRootSignature(const sk_sp< GrD3DRootSignature > &rootSignature)
void setStencilRef(unsigned int stencilRef)
void setPrimitiveTopology(D3D12_PRIMITIVE_TOPOLOGY primitiveTopology)
void setRenderTarget(const GrD3DRenderTarget *renderTarget)
void setBlendFactor(const float blendFactor[4])
void setViewports(unsigned int numViewports, const D3D12_VIEWPORT *viewports)
void clearDepthStencilView(const GrD3DAttachment *, uint8_t stencilClearValue, const D3D12_RECT *rect)
void setPipelineState(const sk_sp< GrD3DPipeline > &pipeline)
void setScissorRects(unsigned int numRects, const D3D12_RECT *rects)
void drawInstanced(unsigned int vertexCount, unsigned int instanceCount, unsigned int startVertex, unsigned int startInstance)
void drawIndexedInstanced(unsigned int indexCount, unsigned int instanceCount, unsigned int startIndex, unsigned int baseVertex, unsigned int startInstance)
GrD3DDirectCommandList * currentCommandList() const
Definition: GrD3DGpu.h:48
void endRenderPass(GrRenderTarget *target, GrSurfaceOrigin origin, const SkIRect &bounds)
Definition: GrD3DGpu.cpp:240
GrD3DResourceProvider & resourceProvider()
Definition: GrD3DGpu.h:38
bool protectedContext() const
Definition: GrD3DGpu.h:55
void inlineUpload(GrOpFlushState *state, GrDeferredTextureUploadFn &upload) override
bool set(GrRenderTarget *, GrSurfaceOrigin, const SkIRect &bounds, const GrOpsRenderPass::LoadAndStoreInfo &, const GrOpsRenderPass::StencilLoadAndStoreInfo &, const skia_private::TArray< GrSurfaceProxy *, true > &sampledProxies)
GrD3DOpsRenderPass(GrD3DGpu *)
void setAndBindTextures(GrD3DGpu *, const GrGeometryProcessor &, const GrSurfaceProxy *const geomProcTextures[], const GrPipeline &)
const sk_sp< GrD3DPipeline > & pipeline() const
void setAndBindConstants(GrD3DGpu *, const GrRenderTarget *, const GrProgramInfo &)
const sk_sp< GrD3DRootSignature > & rootSignature() const
void bindBuffers(GrD3DGpu *, sk_sp< const GrBuffer > indexBuffer, sk_sp< const GrBuffer > instanceBuffer, sk_sp< const GrBuffer > vertexBuffer, GrD3DDirectCommandList *commandList)
const GrD3DTextureResource * msaaTextureResource() const
sk_sp< GrD3DCommandSignature > findOrCreateCommandSignature(GrD3DCommandSignature::ForIndexed, unsigned int slot)
GrD3DPipelineState * findOrCreateCompatiblePipelineState(GrD3DRenderTarget *, const GrProgramInfo &)
D3D12_RESOURCE_STATES getResourceState() const
void setResourceState(const GrD3DGpu *gpu, D3D12_RESOURCE_STATES newResourceState, unsigned int subresource=D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES)
sk_sp< GrD3DResourceState > grD3DResourceState() const
GrDirectContextPriv priv()
const GrDirectContext * getContext() const
void incNumDraws()
Definition: GrGpu.h:541
Definition: GrGpu.h:62
Stats * stats()
Definition: GrGpu.h:551
const GrCaps * caps() const
Definition: GrGpu.h:73
void set(GrRenderTarget *rt, GrSurfaceOrigin origin)
GrSurfaceOrigin fOrigin
GrRenderTarget * fRenderTarget
void visitTextureEffects(const std::function< void(const GrTextureEffect &)> &) const
Definition: GrPipeline.cpp:98
GrTexture * peekDstTexture() const
Definition: GrPipeline.h:145
int numSamples() const
GrAttachment * getStencilAttachment(bool useMSAASurface) const
bool enabled() const
const SkIRect & rect() const
bool isTwoSided() const
const Face & postOriginCCWFace(GrSurfaceOrigin origin) const
bool isDisabled() const
const Face & singleSidedFace() const
const Face & postOriginCWFace(GrSurfaceOrigin origin) const
virtual GrBackendFormat backendFormat() const =0
bool isProtected() const
Definition: GrSurface.h:87
int height() const
Definition: GrSurface.h:37
int width() const
Definition: GrSurface.h:32
GrTexture * texture() const
skgpu::BlendInfo getBlendInfo() const
constexpr std::array< float, 4 > applyTo(std::array< float, 4 > color) const
Definition: Swizzle.h:101
DlColor color
VkSurfaceKHR surface
Definition: main.cc:49
AtkStateType state
Optional< SkRect > bounds
Definition: SkRecords.h:189
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
static constexpr bool BlendCoeffRefsConstant(const BlendCoeff coeff)
Definition: Blend.h:141
BlendCoeff
Definition: Blend.h:60
Definition: upload.py:1
SeparatedVector2 offset
std::array< float, 4 > fClearColor
Definition: SkRect.h:32
bool intersect(const SkIRect &r)
Definition: SkRect.h:513
int32_t fBottom
larger y-axis bounds
Definition: SkRect.h:36
constexpr int32_t height() const
Definition: SkRect.h:165
int32_t fTop
smaller y-axis bounds
Definition: SkRect.h:34
static constexpr SkIRect MakeEmpty()
Definition: SkRect.h:45
void setEmpty()
Definition: SkRect.h:242
static constexpr SkIRect MakeWH(int32_t w, int32_t h)
Definition: SkRect.h:56
bool isEmpty() const
Definition: SkRect.h:202
void setXYWH(int32_t x, int32_t y, int32_t width, int32_t height)
Definition: SkRect.h:268
int32_t fLeft
smaller x-axis bounds
Definition: SkRect.h:33
void setLTRB(int32_t left, int32_t top, int32_t right, int32_t bottom)
Definition: SkRect.h:253
bool contains(int32_t x, int32_t y) const
Definition: SkRect.h:463
int32_t fRight
larger x-axis bounds
Definition: SkRect.h:35
float fB
blue component
Definition: SkColor.h:265
float fR
red component
Definition: SkColor.h:263
float fG
green component
Definition: SkColor.h:264
float fA
alpha component
Definition: SkColor.h:266
static SkRect Make(const SkISize &size)
Definition: SkRect.h:669
bool intersect(const SkRect &r)
Definition: SkRect.cpp:114
void roundOut(SkIRect *dst) const
Definition: SkRect.h:1241
skgpu::BlendCoeff fDstBlend
Definition: Blend.h:96
SkPMColor4f fBlendConstant
Definition: Blend.h:97
skgpu::BlendCoeff fSrcBlend
Definition: Blend.h:95