1 /*
2 * Copyright 2019 Google Inc.
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/dawn/GrDawnOpsRenderPass.h"
9
10 #include "src/gpu/GrFixedClip.h"
11 #include "src/gpu/GrMesh.h"
12 #include "src/gpu/GrOpFlushState.h"
13 #include "src/gpu/GrPipeline.h"
14 #include "src/gpu/GrRenderTargetPriv.h"
15 #include "src/gpu/GrTexturePriv.h"
16 #include "src/gpu/dawn/GrDawnBuffer.h"
17 #include "src/gpu/dawn/GrDawnGpu.h"
18 #include "src/gpu/dawn/GrDawnProgramBuilder.h"
19 #include "src/gpu/dawn/GrDawnRenderTarget.h"
20 #include "src/gpu/dawn/GrDawnStencilAttachment.h"
21 #include "src/gpu/dawn/GrDawnTexture.h"
22 #include "src/gpu/dawn/GrDawnUtil.h"
23 #include "src/sksl/SkSLCompiler.h"
24
25 ////////////////////////////////////////////////////////////////////////////////
26
to_dawn_load_op(GrLoadOp loadOp)27 static dawn::LoadOp to_dawn_load_op(GrLoadOp loadOp) {
28 switch (loadOp) {
29 case GrLoadOp::kLoad:
30 return dawn::LoadOp::Load;
31 case GrLoadOp::kDiscard:
32 // Use LoadOp::Load to emulate DontCare.
33 // Dawn doesn't have DontCare, for security reasons.
34 // Load should be equivalent to DontCare for desktop; Clear would
35 // probably be better for tilers. If Dawn does add DontCare
36 // as an extension, use it here.
37 return dawn::LoadOp::Load;
38 case GrLoadOp::kClear:
39 return dawn::LoadOp::Clear;
40 default:
41 SK_ABORT("Invalid LoadOp");
42 }
43 }
44
GrDawnOpsRenderPass(GrDawnGpu * gpu,GrRenderTarget * rt,GrSurfaceOrigin origin,const LoadAndStoreInfo & colorInfo,const StencilLoadAndStoreInfo & stencilInfo)45 GrDawnOpsRenderPass::GrDawnOpsRenderPass(GrDawnGpu* gpu, GrRenderTarget* rt, GrSurfaceOrigin origin,
46 const LoadAndStoreInfo& colorInfo,
47 const StencilLoadAndStoreInfo& stencilInfo)
48 : INHERITED(rt, origin)
49 , fGpu(gpu)
50 , fColorInfo(colorInfo) {
51 fEncoder = fGpu->device().CreateCommandEncoder();
52 dawn::LoadOp colorOp = to_dawn_load_op(colorInfo.fLoadOp);
53 dawn::LoadOp stencilOp = to_dawn_load_op(stencilInfo.fLoadOp);
54 fPassEncoder = beginRenderPass(colorOp, stencilOp);
55 }
56
beginRenderPass(dawn::LoadOp colorOp,dawn::LoadOp stencilOp)57 dawn::RenderPassEncoder GrDawnOpsRenderPass::beginRenderPass(dawn::LoadOp colorOp,
58 dawn::LoadOp stencilOp) {
59 dawn::Texture texture = static_cast<GrDawnRenderTarget*>(fRenderTarget)->texture();
60 auto stencilAttachment = static_cast<GrDawnStencilAttachment*>(
61 fRenderTarget->renderTargetPriv().getStencilAttachment());
62 dawn::TextureView colorView = texture.CreateView();
63 const float *c = fColorInfo.fClearColor.vec();
64
65 dawn::RenderPassColorAttachmentDescriptor colorAttachment;
66 colorAttachment.attachment = colorView;
67 colorAttachment.resolveTarget = nullptr;
68 colorAttachment.clearColor = { c[0], c[1], c[2], c[3] };
69 colorAttachment.loadOp = colorOp;
70 colorAttachment.storeOp = dawn::StoreOp::Store;
71 dawn::RenderPassColorAttachmentDescriptor* colorAttachments = { &colorAttachment };
72 dawn::RenderPassDescriptor renderPassDescriptor;
73 renderPassDescriptor.colorAttachmentCount = 1;
74 renderPassDescriptor.colorAttachments = colorAttachments;
75 if (stencilAttachment) {
76 dawn::RenderPassDepthStencilAttachmentDescriptor depthStencilAttachment;
77 depthStencilAttachment.attachment = stencilAttachment->view();
78 depthStencilAttachment.depthLoadOp = stencilOp;
79 depthStencilAttachment.stencilLoadOp = stencilOp;
80 depthStencilAttachment.clearDepth = 1.0f;
81 depthStencilAttachment.clearStencil = 0;
82 depthStencilAttachment.depthStoreOp = dawn::StoreOp::Store;
83 depthStencilAttachment.stencilStoreOp = dawn::StoreOp::Store;
84 renderPassDescriptor.depthStencilAttachment = &depthStencilAttachment;
85 } else {
86 renderPassDescriptor.depthStencilAttachment = nullptr;
87 }
88 return fEncoder.BeginRenderPass(&renderPassDescriptor);
89 }
90
~GrDawnOpsRenderPass()91 GrDawnOpsRenderPass::~GrDawnOpsRenderPass() {
92 }
93
gpu()94 GrGpu* GrDawnOpsRenderPass::gpu() { return fGpu; }
95
end()96 void GrDawnOpsRenderPass::end() {
97 fPassEncoder.EndPass();
98 }
99
submit()100 void GrDawnOpsRenderPass::submit() {
101 fGpu->appendCommandBuffer(fEncoder.Finish());
102 }
103
insertEventMarker(const char * msg)104 void GrDawnOpsRenderPass::insertEventMarker(const char* msg) {
105 SkASSERT(!"unimplemented");
106 }
107
onClearStencilClip(const GrFixedClip & clip,bool insideStencilMask)108 void GrDawnOpsRenderPass::onClearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
109 fPassEncoder.EndPass();
110 fPassEncoder = beginRenderPass(dawn::LoadOp::Load, dawn::LoadOp::Clear);
111 }
112
onClear(const GrFixedClip & clip,const SkPMColor4f & color)113 void GrDawnOpsRenderPass::onClear(const GrFixedClip& clip, const SkPMColor4f& color) {
114 fPassEncoder.EndPass();
115 fPassEncoder = beginRenderPass(dawn::LoadOp::Clear, dawn::LoadOp::Load);
116 }
117
118 ////////////////////////////////////////////////////////////////////////////////
119
inlineUpload(GrOpFlushState * state,GrDeferredTextureUploadFn & upload)120 void GrDawnOpsRenderPass::inlineUpload(GrOpFlushState* state,
121 GrDeferredTextureUploadFn& upload) {
122 SkASSERT(!"unimplemented");
123 }
124
125 ////////////////////////////////////////////////////////////////////////////////
126
setScissorState(const GrProgramInfo & programInfo)127 void GrDawnOpsRenderPass::setScissorState(const GrProgramInfo& programInfo) {
128 SkIRect rect;
129 if (programInfo.pipeline().isScissorEnabled()) {
130 constexpr SkIRect kBogusScissor{0, 0, 1, 1};
131 rect = programInfo.hasFixedScissor() ? programInfo.fixedScissor() : kBogusScissor;
132 if (kBottomLeft_GrSurfaceOrigin == fOrigin) {
133 rect.setXYWH(rect.x(), fRenderTarget->height() - rect.bottom(),
134 rect.width(), rect.height());
135 }
136 } else {
137 rect = SkIRect::MakeWH(fRenderTarget->width(), fRenderTarget->height());
138 }
139 fPassEncoder.SetScissorRect(rect.x(), rect.y(), rect.width(), rect.height());
140 }
141
applyState(const GrProgramInfo & programInfo,const GrPrimitiveType primitiveType)142 void GrDawnOpsRenderPass::applyState(const GrProgramInfo& programInfo,
143 const GrPrimitiveType primitiveType) {
144 sk_sp<GrDawnProgram> program = fGpu->getOrCreateRenderPipeline(fRenderTarget,
145 programInfo,
146 primitiveType);
147 auto bindGroup = program->setData(fGpu, fRenderTarget, programInfo);
148 fPassEncoder.SetPipeline(program->fRenderPipeline);
149 fPassEncoder.SetBindGroup(0, bindGroup, 0, nullptr);
150 const GrPipeline& pipeline = programInfo.pipeline();
151 if (pipeline.isStencilEnabled()) {
152 fPassEncoder.SetStencilReference(pipeline.getUserStencil()->fFront.fRef);
153 }
154 GrXferProcessor::BlendInfo blendInfo = pipeline.getXferProcessor().getBlendInfo();
155 const float* c = blendInfo.fBlendConstant.vec();
156 dawn::Color color{c[0], c[1], c[2], c[3]};
157 fPassEncoder.SetBlendColor(&color);
158 this->setScissorState(programInfo);
159 }
160
onDraw(const GrProgramInfo & programInfo,const GrMesh meshes[],int meshCount,const SkRect & bounds)161 void GrDawnOpsRenderPass::onDraw(const GrProgramInfo& programInfo,
162 const GrMesh meshes[],
163 int meshCount,
164 const SkRect& bounds) {
165 if (!meshCount) {
166 return;
167 }
168 for (int i = 0; i < meshCount; ++i) {
169 applyState(programInfo, meshes[0].primitiveType());
170 meshes[i].sendToGpu(this);
171 }
172 }
173
sendInstancedMeshToGpu(GrPrimitiveType,const GrBuffer * vertexBuffer,int vertexCount,int baseVertex,const GrBuffer * instanceBuffer,int instanceCount,int baseInstance)174 void GrDawnOpsRenderPass::sendInstancedMeshToGpu(GrPrimitiveType,
175 const GrBuffer* vertexBuffer,
176 int vertexCount,
177 int baseVertex,
178 const GrBuffer* instanceBuffer,
179 int instanceCount,
180 int baseInstance) {
181 dawn::Buffer vb = static_cast<const GrDawnBuffer*>(vertexBuffer)->get();
182 fPassEncoder.SetVertexBuffer(0, vb);
183 fPassEncoder.Draw(vertexCount, 1, baseVertex, baseInstance);
184 fGpu->stats()->incNumDraws();
185 }
186
sendIndexedInstancedMeshToGpu(GrPrimitiveType,const GrBuffer * indexBuffer,int indexCount,int baseIndex,const GrBuffer * vertexBuffer,int baseVertex,const GrBuffer * instanceBuffer,int instanceCount,int baseInstance,GrPrimitiveRestart restart)187 void GrDawnOpsRenderPass::sendIndexedInstancedMeshToGpu(GrPrimitiveType,
188 const GrBuffer* indexBuffer,
189 int indexCount,
190 int baseIndex,
191 const GrBuffer* vertexBuffer,
192 int baseVertex,
193 const GrBuffer* instanceBuffer,
194 int instanceCount,
195 int baseInstance,
196 GrPrimitiveRestart restart) {
197 dawn::Buffer vb = static_cast<const GrDawnBuffer*>(vertexBuffer)->get();
198 dawn::Buffer ib = static_cast<const GrDawnBuffer*>(indexBuffer)->get();
199 fPassEncoder.SetIndexBuffer(ib);
200 fPassEncoder.SetVertexBuffer(0, vb);
201 fPassEncoder.DrawIndexed(indexCount, 1, baseIndex, baseVertex, baseInstance);
202 fGpu->stats()->incNumDraws();
203 }
204