• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/GrDawnGpu.h"
9 
10 #include "include/gpu/GrBackendSemaphore.h"
11 #include "include/gpu/GrBackendSurface.h"
12 #include "include/gpu/GrContextOptions.h"
13 #include "src/gpu/GrGeometryProcessor.h"
14 #include "src/gpu/GrGpuResourceCacheAccess.h"
15 #include "src/gpu/GrMesh.h"
16 #include "src/gpu/GrPipeline.h"
17 #include "src/gpu/GrRenderTargetPriv.h"
18 #include "src/gpu/GrSemaphore.h"
19 #include "src/gpu/GrTexturePriv.h"
20 #include "src/gpu/dawn/GrDawnBuffer.h"
21 #include "src/gpu/dawn/GrDawnCaps.h"
22 #include "src/gpu/dawn/GrDawnGpuCommandBuffer.h"
23 #include "src/gpu/dawn/GrDawnRenderTarget.h"
24 #include "src/gpu/dawn/GrDawnStencilAttachment.h"
25 #include "src/gpu/dawn/GrDawnTexture.h"
26 #include "src/gpu/dawn/GrDawnUtil.h"
27 
28 #include "src/core/SkAutoMalloc.h"
29 #include "src/core/SkMipMap.h"
30 #include "src/sksl/SkSLCompiler.h"
31 
32 #if !defined(SK_BUILD_FOR_WIN)
33 #include <unistd.h>
34 #endif // !defined(SK_BUILD_FOR_WIN)
35 
Make(const dawn::Device & device,const GrContextOptions & options,GrContext * context)36 sk_sp<GrGpu> GrDawnGpu::Make(const dawn::Device& device,
37                              const GrContextOptions& options, GrContext* context) {
38     if (!device) {
39         return nullptr;
40     }
41 
42     return sk_sp<GrGpu>(new GrDawnGpu(context, options, device));
43 }
44 
45 ////////////////////////////////////////////////////////////////////////////////
46 
GrDawnGpu(GrContext * context,const GrContextOptions & options,const dawn::Device & device)47 GrDawnGpu::GrDawnGpu(GrContext* context, const GrContextOptions& options,
48                      const dawn::Device& device)
49         : INHERITED(context)
50         , fDevice(device)
51         , fQueue(device.CreateQueue())
52         , fCompiler(new SkSL::Compiler()) {
53     fCaps.reset(new GrDawnCaps(options));
54 }
55 
~GrDawnGpu()56 GrDawnGpu::~GrDawnGpu() {
57 }
58 
59 
disconnect(DisconnectType type)60 void GrDawnGpu::disconnect(DisconnectType type) {
61     SkASSERT(!"unimplemented");
62 }
63 
64 ///////////////////////////////////////////////////////////////////////////////
65 
getCommandBuffer(GrRenderTarget * rt,GrSurfaceOrigin origin,const SkRect & bounds,const GrGpuRTCommandBuffer::LoadAndStoreInfo & colorInfo,const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo & stencilInfo)66 GrGpuRTCommandBuffer* GrDawnGpu::getCommandBuffer(
67             GrRenderTarget* rt, GrSurfaceOrigin origin, const SkRect& bounds,
68             const GrGpuRTCommandBuffer::LoadAndStoreInfo& colorInfo,
69             const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo& stencilInfo) {
70     fRTCommandBuffer.reset(new GrDawnGpuRTCommandBuffer(this, rt, origin, colorInfo, stencilInfo));
71     return fRTCommandBuffer.get();
72 }
73 
getCommandBuffer(GrTexture * texture,GrSurfaceOrigin origin)74 GrGpuTextureCommandBuffer* GrDawnGpu::getCommandBuffer(GrTexture* texture,
75                                                        GrSurfaceOrigin origin) {
76     fTextureCommandBuffer.reset(new GrDawnGpuTextureCommandBuffer(this, texture, origin));
77     return fTextureCommandBuffer.get();
78 }
79 
80 ///////////////////////////////////////////////////////////////////////////////
onCreateBuffer(size_t size,GrGpuBufferType type,GrAccessPattern accessPattern,const void * data)81 sk_sp<GrGpuBuffer> GrDawnGpu::onCreateBuffer(size_t size, GrGpuBufferType type,
82                                              GrAccessPattern accessPattern, const void* data) {
83     sk_sp<GrGpuBuffer> b(new GrDawnBuffer(this, size, type, accessPattern));
84     if (data && b) {
85         b->updateData(data, size);
86     }
87     return b;
88 }
89 
90 ////////////////////////////////////////////////////////////////////////////////
onWritePixels(GrSurface * surface,int left,int top,int width,int height,GrColorType textureColorType,GrColorType bufferColorType,const GrMipLevel texels[],int mipLevelCount)91 bool GrDawnGpu::onWritePixels(GrSurface* surface, int left, int top, int width, int height,
92                               GrColorType textureColorType, GrColorType bufferColorType,
93                               const GrMipLevel texels[], int mipLevelCount) {
94     GrDawnTexture* texture = static_cast<GrDawnTexture*>(surface->asTexture());
95     if (!texture) {
96         SkASSERT(!"uploading to non-texture unimplemented");
97         return false;
98     }
99     texture->upload(texels, mipLevelCount, SkIRect::MakeXYWH(left, top, width, height));
100     return true;
101 }
102 
onTransferPixelsTo(GrTexture * texture,int left,int top,int width,int height,GrColorType textureColorType,GrColorType bufferColorType,GrGpuBuffer * transferBuffer,size_t bufferOffset,size_t rowBytes)103 bool GrDawnGpu::onTransferPixelsTo(GrTexture* texture, int left, int top, int width, int height,
104                                    GrColorType textureColorType, GrColorType bufferColorType,
105                                    GrGpuBuffer* transferBuffer, size_t bufferOffset,
106                                    size_t rowBytes) {
107     SkASSERT(!"unimplemented");
108     return false;
109 }
110 
onTransferPixelsFrom(GrSurface * surface,int left,int top,int width,int height,GrColorType surfaceColorType,GrColorType bufferColorType,GrGpuBuffer * transferBuffer,size_t offset)111 bool GrDawnGpu::onTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
112                                      GrColorType surfaceColorType, GrColorType bufferColorType,
113                                      GrGpuBuffer* transferBuffer, size_t offset) {
114     SkASSERT(!"unimplemented");
115     return false;
116 }
117 
118 ////////////////////////////////////////////////////////////////////////////////
onCreateTexture(const GrSurfaceDesc & desc,const GrBackendFormat & backendFormat,GrRenderable renderable,int renderTargetSampleCnt,SkBudgeted budgeted,GrProtected,const GrMipLevel texels[],int mipLevelCount)119 sk_sp<GrTexture> GrDawnGpu::onCreateTexture(const GrSurfaceDesc& desc,
120                                             const GrBackendFormat& backendFormat,
121                                             GrRenderable renderable,
122                                             int renderTargetSampleCnt,
123                                             SkBudgeted budgeted,
124                                             GrProtected,
125                                             const GrMipLevel texels[],
126                                             int mipLevelCount) {
127     dawn::TextureFormat format;
128     if (!backendFormat.asDawnFormat(&format)) {
129         return nullptr;
130     }
131 
132     GrMipMapsStatus mipMapsStatus = GrMipMapsStatus::kNotAllocated;
133     if (mipLevelCount > 1) {
134         mipMapsStatus = GrMipMapsStatus::kValid;
135         for (int i = 0; i < mipLevelCount; ++i) {
136             if (!texels[i].fPixels) {
137                 mipMapsStatus = GrMipMapsStatus::kDirty;
138                 break;
139             }
140         }
141     }
142 
143     sk_sp<GrDawnTexture> tex = GrDawnTexture::Make(this, { desc.fWidth, desc.fHeight },
144                                                    desc.fConfig, format, renderable,
145                                                    renderTargetSampleCnt, budgeted, mipLevelCount,
146                                                    mipMapsStatus);
147     if (!tex) {
148         return nullptr;
149     }
150     tex->upload(texels, mipLevelCount);
151     return tex;
152 }
153 
onCreateCompressedTexture(int width,int height,const GrBackendFormat &,SkImage::CompressionType,SkBudgeted,const void * data)154 sk_sp<GrTexture> GrDawnGpu::onCreateCompressedTexture(int width, int height, const GrBackendFormat&,
155                                                       SkImage::CompressionType, SkBudgeted,
156                                                       const void* data) {
157     SkASSERT(!"unimplemented");
158     return nullptr;
159 }
160 
onWrapBackendTexture(const GrBackendTexture & backendTex,GrColorType colorType,GrWrapOwnership ownership,GrWrapCacheable cacheable,GrIOType)161 sk_sp<GrTexture> GrDawnGpu::onWrapBackendTexture(const GrBackendTexture& backendTex,
162                                                  GrColorType colorType,
163                                                  GrWrapOwnership ownership,
164                                                  GrWrapCacheable cacheable,
165                                                  GrIOType) {
166     GrDawnImageInfo info;
167     if (!backendTex.getDawnImageInfo(&info)) {
168         return nullptr;
169     }
170 
171     SkISize size = { backendTex.width(), backendTex.height() };
172     GrPixelConfig config = this->caps()->getConfigFromBackendFormat(backendTex.getBackendFormat(),
173                                                                     colorType);
174     GrMipMapsStatus status = GrMipMapsStatus::kNotAllocated;
175     return GrDawnTexture::MakeWrapped(this, size, config, status, cacheable, info);
176 }
177 
onWrapRenderableBackendTexture(const GrBackendTexture & tex,int sampleCnt,GrColorType,GrWrapOwnership,GrWrapCacheable cacheable)178 sk_sp<GrTexture> GrDawnGpu::onWrapRenderableBackendTexture(const GrBackendTexture& tex,
179                                                            int sampleCnt, GrColorType,
180                                                            GrWrapOwnership,
181                                                            GrWrapCacheable cacheable) {
182     SkASSERT(!"unimplemented");
183     return nullptr;
184 }
185 
onWrapBackendRenderTarget(const GrBackendRenderTarget &,GrColorType colorType)186 sk_sp<GrRenderTarget> GrDawnGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget&,
187                                                            GrColorType colorType) {
188     SkASSERT(!"unimplemented");
189     return nullptr;
190 }
191 
onWrapBackendTextureAsRenderTarget(const GrBackendTexture & tex,int sampleCnt,GrColorType colorType)192 sk_sp<GrRenderTarget> GrDawnGpu::onWrapBackendTextureAsRenderTarget(const GrBackendTexture& tex,
193                                                                     int sampleCnt,
194                                                                     GrColorType colorType) {
195     GrDawnImageInfo info;
196     if (!tex.getDawnImageInfo(&info)) {
197         return nullptr;
198     }
199     if (!info.fTexture) {
200         return nullptr;
201     }
202 
203     GrSurfaceDesc desc;
204     SkISize size = { tex.width(), tex.height() };
205     GrPixelConfig config = this->caps()->getConfigFromBackendFormat(tex.getBackendFormat(),
206                                                                     colorType);
207     sampleCnt = this->caps()->getRenderTargetSampleCount(sampleCnt, tex.getBackendFormat());
208     if (sampleCnt < 1) {
209         return nullptr;
210     }
211 
212     return GrDawnRenderTarget::MakeWrapped(this, size, config, sampleCnt, info);
213 }
214 
createStencilAttachmentForRenderTarget(const GrRenderTarget * rt,int width,int height,int numStencilSamples)215 GrStencilAttachment* GrDawnGpu::createStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
216                                                                        int width,
217                                                                        int height,
218                                                                        int numStencilSamples) {
219     GrDawnStencilAttachment* stencil(GrDawnStencilAttachment::Create(this,
220                                                                      width,
221                                                                      height,
222                                                                      numStencilSamples));
223     fStats.incStencilAttachmentCreates();
224     return stencil;
225 }
226 
createBackendTexture(int width,int height,const GrBackendFormat & backendFormat,GrMipMapped mipMapped,GrRenderable renderable,const void * pixels,size_t rowBytes,const SkColor4f * color,GrProtected isProtected)227 GrBackendTexture GrDawnGpu::createBackendTexture(int width, int height,
228                                                  const GrBackendFormat& backendFormat,
229                                                  GrMipMapped mipMapped,
230                                                  GrRenderable renderable,
231                                                  const void* pixels,
232                                                  size_t rowBytes,
233                                                  const SkColor4f* color,
234                                                  GrProtected isProtected) {
235     dawn::TextureFormat format;
236     if (!backendFormat.asDawnFormat(&format)) {
237         return GrBackendTexture();
238     }
239 
240     GrPixelConfig config = GrDawnFormatToPixelConfig(format);
241 
242     if (width > this->caps()->maxTextureSize() || height > this->caps()->maxTextureSize()) {
243         return GrBackendTexture();
244     }
245 
246     // Currently we don't support uploading pixel data when mipped.
247     if (pixels && GrMipMapped::kYes == mipMapped) {
248         return GrBackendTexture();
249     }
250 
251     dawn::TextureDescriptor desc;
252     desc.usage =
253         dawn::TextureUsageBit::Sampled |
254         dawn::TextureUsageBit::CopySrc |
255         dawn::TextureUsageBit::CopyDst;
256 
257     if (GrRenderable::kYes == renderable) {
258         desc.usage |= dawn::TextureUsageBit::OutputAttachment;
259     }
260 
261     desc.size.width = width;
262     desc.size.height = height;
263     desc.size.depth = 1;
264     desc.format = format;
265 
266     // Figure out the number of mip levels.
267     if (GrMipMapped::kYes == mipMapped) {
268         desc.mipLevelCount = SkMipMap::ComputeLevelCount(width, height) + 1;
269     }
270 
271     dawn::Texture tex = this->device().CreateTexture(&desc);
272 
273     size_t bpp = GrBytesPerPixel(config);
274     size_t baseLayerSize = bpp * width * height;
275     SkAutoMalloc defaultStorage(baseLayerSize);
276     if (!pixels) {
277         // Fill in the texture with all zeros so we don't have random garbage
278         pixels = defaultStorage.get();
279         memset(defaultStorage.get(), 0, baseLayerSize);
280     }
281     dawn::Device device = this->device();
282     dawn::CommandEncoder copyEncoder = fDevice.CreateCommandEncoder();
283     int w = width, h = height;
284     for (uint32_t i = 0; i < desc.mipLevelCount; i++) {
285         size_t origRowBytes = bpp * w;
286         size_t rowBytes = GrDawnRoundRowBytes(origRowBytes);
287         size_t size = rowBytes * h;
288         dawn::BufferDescriptor bufferDesc;
289         bufferDesc.size = size;
290         bufferDesc.usage = dawn::BufferUsageBit::CopySrc | dawn::BufferUsageBit::CopyDst;
291         dawn::Buffer buffer = this->device().CreateBuffer(&bufferDesc);
292         const uint8_t* src = static_cast<const uint8_t*>(pixels);
293         if (rowBytes == origRowBytes) {
294             buffer.SetSubData(0, size, src);
295         } else {
296             uint32_t offset = 0;
297             for (int row = 0; row < h; row++) {
298                 buffer.SetSubData(offset, origRowBytes, src);
299                 offset += rowBytes;
300                 src += origRowBytes;
301             }
302         }
303         dawn::BufferCopyView srcBuffer;
304         srcBuffer.buffer = buffer;
305         srcBuffer.offset = 0;
306         srcBuffer.rowPitch = rowBytes;
307         srcBuffer.imageHeight = h;
308         dawn::TextureCopyView dstTexture;
309         dstTexture.texture = tex;
310         dstTexture.mipLevel = i;
311         dstTexture.origin = {0, 0, 0};
312         dawn::Extent3D copySize = {(uint32_t) w, (uint32_t) h, 1};
313         copyEncoder.CopyBufferToTexture(&srcBuffer, &dstTexture, &copySize);
314         w = SkTMax(1, w / 2);
315         h = SkTMax(1, h / 2);
316     }
317     dawn::CommandBuffer cmdBuf = copyEncoder.Finish();
318     fQueue.Submit(1, &cmdBuf);
319     GrDawnImageInfo info;
320     info.fTexture = tex;
321     info.fFormat = desc.format;
322     info.fLevelCount = desc.mipLevelCount;
323     return GrBackendTexture(width, height, info);
324 }
325 
deleteBackendTexture(const GrBackendTexture & tex)326 void GrDawnGpu::deleteBackendTexture(const GrBackendTexture& tex) {
327     SkASSERT(!"unimplemented");
328 }
329 
330 #if GR_TEST_UTILS
isTestingOnlyBackendTexture(const GrBackendTexture & tex) const331 bool GrDawnGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
332     SkASSERT(!"unimplemented");
333     return false;
334 }
335 
createTestingOnlyBackendRenderTarget(int w,int h,GrColorType)336 GrBackendRenderTarget GrDawnGpu::createTestingOnlyBackendRenderTarget(int w, int h, GrColorType) {
337     SkASSERT(!"unimplemented");
338     return GrBackendRenderTarget();
339 }
340 
deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget &)341 void GrDawnGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) {
342     SkASSERT(!"unimplemented");
343 }
344 
testingOnly_flushGpuAndSync()345 void GrDawnGpu::testingOnly_flushGpuAndSync() {
346     SkASSERT(!"unimplemented");
347 }
348 
349 #endif
350 
onFinishFlush(GrSurfaceProxy * [],int n,SkSurface::BackendSurfaceAccess access,const GrFlushInfo & info,const GrPrepareForExternalIORequests &)351 void GrDawnGpu::onFinishFlush(GrSurfaceProxy*[], int n, SkSurface::BackendSurfaceAccess access,
352                               const GrFlushInfo& info, const GrPrepareForExternalIORequests&) {
353     SkASSERT(!"unimplemented");
354 }
355 
onCopySurface(GrSurface * dst,GrSurface * src,const SkIRect & srcRect,const SkIPoint & dstPoint,bool canDiscardOutsideDstRect)356 bool GrDawnGpu::onCopySurface(GrSurface* dst,
357                               GrSurface* src,
358                               const SkIRect& srcRect,
359                               const SkIPoint& dstPoint,
360                               bool canDiscardOutsideDstRect) {
361     SkASSERT(!"unimplemented");
362     return false;
363 }
364 
callback(DawnBufferMapAsyncStatus status,const void * data,uint64_t dataLength,void * userdata)365 static void callback(DawnBufferMapAsyncStatus status, const void* data, uint64_t dataLength,
366                      void* userdata) {
367     (*reinterpret_cast<const void**>(userdata)) = data;
368 }
369 
onReadPixels(GrSurface * surface,int left,int top,int width,int height,GrColorType surfaceColorType,GrColorType dstColorType,void * buffer,size_t rowBytes)370 bool GrDawnGpu::onReadPixels(GrSurface* surface, int left, int top, int width, int height,
371                              GrColorType surfaceColorType, GrColorType dstColorType, void* buffer,
372                              size_t rowBytes) {
373     dawn::Texture tex = static_cast<GrDawnTexture*>(surface->asTexture())->texture();
374 
375     size_t origRowBytes = rowBytes;
376     int origSizeInBytes = origRowBytes * height;
377     rowBytes = GrDawnRoundRowBytes(rowBytes);
378     int sizeInBytes = rowBytes * height;
379 
380     dawn::BufferDescriptor desc;
381     desc.usage = dawn::BufferUsageBit::CopyDst | dawn::BufferUsageBit::MapRead;
382     desc.size = sizeInBytes;
383 
384     dawn::Buffer buf = device().CreateBuffer(&desc);
385 
386     dawn::TextureCopyView srcTexture;
387     srcTexture.texture = tex;
388     srcTexture.origin = {(uint32_t) left, (uint32_t) top, 0};
389 
390     dawn::BufferCopyView dstBuffer;
391     dstBuffer.buffer = buf;
392     dstBuffer.offset = 0;
393     dstBuffer.rowPitch = rowBytes;
394     dstBuffer.imageHeight = height;
395 
396     dawn::Extent3D copySize = {(uint32_t) width, (uint32_t) height, 1};
397     auto encoder = device().CreateCommandEncoder();
398     encoder.CopyTextureToBuffer(&srcTexture, &dstBuffer, &copySize);
399     auto commandBuffer = encoder.Finish();
400     queue().Submit(1, &commandBuffer);
401 
402     const void *readPixelsPtr = nullptr;
403     buf.MapReadAsync(callback, &readPixelsPtr);
404     while (!readPixelsPtr) {
405         device().Tick();
406     }
407 
408     if (rowBytes == origRowBytes) {
409         memcpy(buffer, readPixelsPtr, origSizeInBytes);
410     } else {
411         const char* src = static_cast<const char*>(readPixelsPtr);
412         char* dst = static_cast<char*>(buffer);
413         for (int row = 0; row < height; row++) {
414             memcpy(dst, src, origRowBytes);
415             dst += origRowBytes;
416             src += rowBytes;
417         }
418     }
419     buf.Unmap();
420     return true;
421 }
422 
onRegenerateMipMapLevels(GrTexture *)423 bool GrDawnGpu::onRegenerateMipMapLevels(GrTexture*) {
424     SkASSERT(!"unimplemented");
425     return false;
426 }
427 
submit(GrGpuCommandBuffer * buffer)428 void GrDawnGpu::submit(GrGpuCommandBuffer* buffer) {
429     if (buffer->asRTCommandBuffer()) {
430         SkASSERT(fRTCommandBuffer.get() == buffer);
431         fRTCommandBuffer->submit();
432     } else {
433         SkASSERT(fTextureCommandBuffer.get() == buffer);
434         fTextureCommandBuffer->submit();
435     }
436 }
437 
insertFence()438 GrFence SK_WARN_UNUSED_RESULT GrDawnGpu::insertFence() {
439     SkASSERT(!"unimplemented");
440     return GrFence();
441 }
442 
waitFence(GrFence fence,uint64_t timeout)443 bool GrDawnGpu::waitFence(GrFence fence, uint64_t timeout) {
444     SkASSERT(!"unimplemented");
445     return false;
446 }
447 
deleteFence(GrFence fence) const448 void GrDawnGpu::deleteFence(GrFence fence) const {
449     SkASSERT(!"unimplemented");
450 }
451 
makeSemaphore(bool isOwned)452 sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT GrDawnGpu::makeSemaphore(bool isOwned) {
453     SkASSERT(!"unimplemented");
454     return nullptr;
455 }
456 
wrapBackendSemaphore(const GrBackendSemaphore & semaphore,GrResourceProvider::SemaphoreWrapType wrapType,GrWrapOwnership ownership)457 sk_sp<GrSemaphore> GrDawnGpu::wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
458                                                    GrResourceProvider::SemaphoreWrapType wrapType,
459                                                    GrWrapOwnership ownership) {
460     SkASSERT(!"unimplemented");
461     return nullptr;
462 }
463 
insertSemaphore(sk_sp<GrSemaphore> semaphore)464 void GrDawnGpu::insertSemaphore(sk_sp<GrSemaphore> semaphore) {
465     SkASSERT(!"unimplemented");
466 }
467 
waitSemaphore(sk_sp<GrSemaphore> semaphore)468 void GrDawnGpu::waitSemaphore(sk_sp<GrSemaphore> semaphore) {
469     SkASSERT(!"unimplemented");
470 }
471 
checkFinishProcs()472 void GrDawnGpu::checkFinishProcs() {
473     SkASSERT(!"unimplemented");
474 }
475 
prepareTextureForCrossContextUsage(GrTexture * texture)476 sk_sp<GrSemaphore> GrDawnGpu::prepareTextureForCrossContextUsage(GrTexture* texture) {
477     SkASSERT(!"unimplemented");
478     return nullptr;
479 }
480