First draft of Dawn backend: clears are working.
First draft of (mostly stubbed-out) GrDawnGpu.
Skeletons of GrDawnCaps, GrDawnGpuCommandBuffer, GrDawnRenderTarget.
First draft of DawnTestContext.
First draft of psuedo-fences for Dawn, implemented with MapReadAsync.
Change-Id: Id009436f4441f26ffbc82d485d7af3a499b3281b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/226857
Commit-Queue: Stephen White <senorblanco@chromium.org>
Reviewed-by: Greg Daniel <egdaniel@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index 5010b05..72c3833 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -649,6 +649,7 @@
if (skia_use_dawn) {
public_defines += [ "SK_DAWN" ]
+ sources += skia_dawn_sources
public_deps += [
"//third_party/dawn:dawn_headers",
"//third_party/dawn:libdawn",
@@ -1565,6 +1566,10 @@
if (skia_use_metal) {
sources += [ "tools/gpu/mtl/MtlTestContext.mm" ]
}
+ if (skia_use_dawn) {
+ public_deps += [ "//third_party/dawn:dawn_headers" ]
+ sources += [ "tools/gpu/dawn/DawnTestContext.cpp" ]
+ }
}
test_lib("flags") {
diff --git a/gn/gpu.gni b/gn/gpu.gni
index 253400c..f7daf4c 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -704,6 +704,19 @@
"$_src/gpu/vk/GrVkVertexBuffer.h",
]
+skia_dawn_sources = [
+ "$_src/gpu/dawn/GrDawnCaps.cpp",
+ "$_src/gpu/dawn/GrDawnCaps.h",
+ "$_src/gpu/dawn/GrDawnGpu.cpp",
+ "$_src/gpu/dawn/GrDawnGpu.h",
+ "$_src/gpu/dawn/GrDawnGpuCommandBuffer.cpp",
+ "$_src/gpu/dawn/GrDawnGpuCommandBuffer.h",
+ "$_src/gpu/dawn/GrDawnRenderTarget.cpp",
+ "$_src/gpu/dawn/GrDawnRenderTarget.h",
+ "$_src/gpu/dawn/GrDawnUtil.cpp",
+ "$_src/gpu/dawn/GrDawnUtil.h",
+]
+
skia_metal_sources = [
"$_include/gpu/mtl/GrMtlTypes.h",
"$_src/gpu/mtl/GrMtlBuffer.h",
diff --git a/include/gpu/GrBackendSurface.h b/include/gpu/GrBackendSurface.h
index 8573626..cf7543f 100644
--- a/include/gpu/GrBackendSurface.h
+++ b/include/gpu/GrBackendSurface.h
@@ -15,9 +15,17 @@
#include "include/private/GrGLTypesPriv.h"
#include "include/private/GrVkTypesPriv.h"
+#ifdef SK_DAWN
+#include "include/gpu/dawn/GrDawnTypes.h"
+#endif
+
class GrVkImageLayout;
class GrGLTextureParameters;
+#ifdef SK_DAWN
+#include "dawn/dawncpp.h"
+#endif
+
#ifdef SK_METAL
#include "include/gpu/mtl/GrMtlTypes.h"
#endif
@@ -60,6 +68,12 @@
// external format.
static GrBackendFormat MakeVk(const GrVkYcbcrConversionInfo& ycbcrInfo);
+#ifdef SK_DAWN
+ static GrBackendFormat MakeDawn(dawn::TextureFormat format) {
+ return GrBackendFormat(format);
+ }
+#endif
+
#ifdef SK_METAL
static GrBackendFormat MakeMtl(GrMTLPixelFormat format) {
return GrBackendFormat(format);
@@ -87,6 +101,10 @@
const GrVkYcbcrConversionInfo* getVkYcbcrConversionInfo() const;
+#ifdef SK_DAWN
+ const dawn::TextureFormat* getDawnFormat() const;
+#endif
+
#ifdef SK_METAL
// If the backend API is Metal, this returns a pointer to a GrMTLPixelFormat. Otherwise
// it returns nullptr
@@ -110,6 +128,10 @@
GrBackendFormat(const VkFormat vkFormat, const GrVkYcbcrConversionInfo&);
+#ifdef SK_DAWN
+ GrBackendFormat(dawn::TextureFormat format);
+#endif
+
#ifdef SK_METAL
GrBackendFormat(const GrMTLPixelFormat mtlFormat);
#endif
@@ -125,6 +147,10 @@
VkFormat fFormat;
GrVkYcbcrConversionInfo fYcbcrConversionInfo;
} fVk;
+#ifdef SK_DAWN
+ dawn::TextureFormat fDawnFormat;
+#endif
+
#ifdef SK_METAL
GrMTLPixelFormat fMtlFormat;
#endif
@@ -160,6 +186,12 @@
const GrMtlTextureInfo& mtlInfo);
#endif
+#ifdef SK_DAWN
+ GrBackendTexture(int width,
+ int height,
+ const GrDawnImageInfo& dawnInfo);
+#endif
+
GrBackendTexture(int width,
int height,
GrMipMapped,
@@ -184,6 +216,12 @@
// externally to GrContext.
void glTextureParametersModified();
+#ifdef SK_DAWN
+ // If the backend API is Dawn, copies a snapshot of the GrDawnImageInfo struct into the passed
+ // in pointer and returns true. Otherwise returns false if the backend API is not Dawn.
+ bool getDawnImageInfo(GrDawnImageInfo*) const;
+#endif
+
// If the backend API is Vulkan, copies a snapshot of the GrVkImageInfo struct into the passed
// in pointer and returns true. This snapshot will set the fImageLayout to the current layout
// state. Otherwise returns false if the backend API is not Vulkan.
@@ -239,6 +277,7 @@
friend class GrProxyProvider;
friend class GrGpu;
friend class GrGLGpu;
+ friend class GrDawnGpu;
friend class GrVkGpu;
friend class GrMtlGpu;
friend class PromiseImageHelper;
@@ -286,6 +325,9 @@
#ifdef SK_METAL
GrMtlTextureInfo fMtlInfo;
#endif
+#ifdef SK_DAWN
+ GrDawnImageInfo fDawnInfo;
+#endif
};
class SK_API GrBackendRenderTarget {
@@ -300,6 +342,14 @@
int stencilBits,
const GrGLFramebufferInfo& glInfo);
+#ifdef SK_DAWN
+ GrBackendRenderTarget(int width,
+ int height,
+ int sampleCnt,
+ int stencilBits,
+ const GrDawnImageInfo& dawnInfo);
+#endif
+
/** Deprecated, use version that does not take stencil bits. */
GrBackendRenderTarget(int width,
int height,
@@ -341,6 +391,12 @@
// in pointer and returns true. Otherwise returns false if the backend API is not GL.
bool getGLFramebufferInfo(GrGLFramebufferInfo*) const;
+#ifdef SK_DAWN
+ // If the backend API is Dawn, copies a snapshot of the GrDawnImageInfo struct into the passed
+ // in pointer and returns true. Otherwise returns false if the backend API is not Dawn.
+ bool getDawnImageInfo(GrDawnImageInfo*) const;
+#endif
+
// If the backend API is Vulkan, copies a snapshot of the GrVkImageInfo struct into the passed
// in pointer and returns true. This snapshot will set the fImageLayout to the current layout
// state. Otherwise returns false if the backend API is not Vulkan.
@@ -387,6 +443,7 @@
friend class SkImage_Gpu;
friend class GrGpu;
friend class GrGLGpu;
+ friend class GrDawnGpu;
friend class GrProxyProvider;
friend class GrVkGpu;
friend class GrMtlGpu;
@@ -423,6 +480,9 @@
#ifdef SK_METAL
GrMtlTextureInfo fMtlInfo;
#endif
+#ifdef SK_DAWN
+ GrDawnImageInfo fDawnInfo;
+#endif
};
#endif
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index 069b071..7556ff2 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -70,6 +70,11 @@
static sk_sp<GrContext> MakeMetal(void* device, void* queue);
#endif
+#ifdef SK_DAWN
+ static sk_sp<GrContext> MakeDawn(const dawn::Device& device, const GrContextOptions& options);
+ static sk_sp<GrContext> MakeDawn(const dawn::Device& device);
+#endif
+
static sk_sp<GrContext> MakeMock(const GrMockOptions*, const GrContextOptions&);
static sk_sp<GrContext> MakeMock(const GrMockOptions*);
diff --git a/include/gpu/GrTypes.h b/include/gpu/GrTypes.h
index e56347d..679a0fa 100644
--- a/include/gpu/GrTypes.h
+++ b/include/gpu/GrTypes.h
@@ -182,6 +182,7 @@
*/
enum class GrBackendApi : unsigned {
kMetal,
+ kDawn,
kOpenGL,
kVulkan,
/**
diff --git a/include/gpu/dawn/GrDawnTypes.h b/include/gpu/dawn/GrDawnTypes.h
new file mode 100644
index 0000000..f8936c2
--- /dev/null
+++ b/include/gpu/dawn/GrDawnTypes.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrDawnTypes_DEFINED
+#define GrDawnTypes_DEFINED
+
+#ifdef Always
+#undef Always
+#endif
+#include "dawn/dawncpp.h"
+
+struct GrDawnImageInfo {
+ dawn::Texture fTexture;
+ dawn::TextureFormat fFormat;
+ uint32_t fLevelCount;
+ GrDawnImageInfo() : fTexture(nullptr), fFormat(), fLevelCount(0) {
+ }
+ GrDawnImageInfo(const GrDawnImageInfo& other)
+ : fTexture(other.fTexture)
+ , fFormat(other.fFormat)
+ , fLevelCount(other.fLevelCount) {
+ }
+ GrDawnImageInfo& operator=(const GrDawnImageInfo& other) {
+ fTexture = other.fTexture;
+ fFormat = other.fFormat;
+ fLevelCount = other.fLevelCount;
+ return *this;
+ }
+ bool operator==(const GrDawnImageInfo& other) const {
+ return fTexture.Get() == other.fTexture.Get() &&
+ fFormat == other.fFormat &&
+ fLevelCount == other.fLevelCount;
+ }
+};
+
+#endif
diff --git a/src/gpu/GrBackendSurface.cpp b/src/gpu/GrBackendSurface.cpp
index 8b3e2f1..77a5617 100644
--- a/src/gpu/GrBackendSurface.cpp
+++ b/src/gpu/GrBackendSurface.cpp
@@ -10,6 +10,11 @@
#include "src/gpu/gl/GrGLUtil.h"
+#ifdef SK_DAWN
+#include "include/gpu/dawn/GrDawnTypes.h"
+#include "src/gpu/dawn/GrDawnUtil.h"
+#endif
+
#ifdef SK_VULKAN
#include "include/gpu/vk/GrVkTypes.h"
#include "src/gpu/vk/GrVkImageLayout.h"
@@ -44,6 +49,11 @@
fMtlFormat = that.fMtlFormat;
break;
#endif
+#ifdef SK_DAWN
+ case GrBackendApi::kDawn:
+ fDawnFormat = that.fDawnFormat;
+ break;
+#endif
case GrBackendApi::kMock:
fMockColorType = that.fMockColorType;
break;
@@ -138,6 +148,22 @@
return nullptr;
}
+#ifdef SK_DAWN
+GrBackendFormat::GrBackendFormat(dawn::TextureFormat format)
+ : fBackend(GrBackendApi::kDawn)
+ , fValid(true)
+ , fDawnFormat(format)
+ , fTextureType(GrTextureType::k2D) {
+}
+
+const dawn::TextureFormat* GrBackendFormat::getDawnFormat() const {
+ if (this->isValid() && GrBackendApi::kDawn == fBackend) {
+ return &fDawnFormat;
+ }
+ return nullptr;
+}
+#endif
+
#ifdef SK_METAL
GrBackendFormat::GrBackendFormat(GrMTLPixelFormat mtlFormat)
: fBackend(GrBackendApi::kMetal)
@@ -207,6 +233,11 @@
return fMtlFormat == that.fMtlFormat;
#endif
break;
+ case GrBackendApi::kDawn:
+#ifdef SK_DAWN
+ return fDawnFormat == that.fDawnFormat;
+#endif
+ break;
case GrBackendApi::kMock:
return fMockColorType == that.fMockColorType;
default:
@@ -215,6 +246,19 @@
return false;
}
+#ifdef SK_DAWN
+GrBackendTexture::GrBackendTexture(int width,
+ int height,
+ const GrDawnImageInfo& dawnInfo)
+ : fIsValid(true)
+ , fWidth(width)
+ , fHeight(height)
+ , fConfig(GrDawnFormatToPixelConfig(dawnInfo.fFormat))
+ , fMipMapped(GrMipMapped(dawnInfo.fLevelCount > 1))
+ , fBackend(GrBackendApi::kDawn)
+ , fDawnInfo(dawnInfo) {}
+#endif
+
GrBackendTexture::GrBackendTexture(int width,
int height,
const GrVkImageInfo& vkInfo)
@@ -357,6 +401,11 @@
fMtlInfo = that.fMtlInfo;
break;
#endif
+#ifdef SK_DAWN
+ case GrBackendApi::kDawn:
+ fDawnInfo = that.fDawnInfo;
+ break;
+#endif
case GrBackendApi::kMock:
fMockInfo = that.fMockInfo;
break;
@@ -367,6 +416,16 @@
return *this;
}
+#ifdef SK_DAWN
+bool GrBackendTexture::getDawnImageInfo(GrDawnImageInfo* outInfo) const {
+ if (this->isValid() && GrBackendApi::kDawn == fBackend) {
+ *outInfo = fDawnInfo;
+ return true;
+ }
+ return false;
+}
+#endif
+
bool GrBackendTexture::getVkImageInfo(GrVkImageInfo* outInfo) const {
#ifdef SK_VULKAN
if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
@@ -484,6 +543,11 @@
return GrBackendFormat::MakeVk(info.fFormat);
}
#endif
+#ifdef SK_DAWN
+ case GrBackendApi::kDawn: {
+ return GrBackendFormat::MakeDawn(fDawnInfo.fFormat);
+ }
+#endif
#ifdef SK_METAL
case GrBackendApi::kMetal: {
GrMtlTextureInfo mtlInfo;
@@ -527,6 +591,10 @@
case GrBackendApi::kMetal:
return t0.fMtlInfo == t1.fMtlInfo;
#endif
+#ifdef SK_DAWN
+ case GrBackendApi::kDawn:
+ return t0.fDawnInfo == t1.fDawnInfo;
+#endif
default:
return false;
}
@@ -535,6 +603,22 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef SK_DAWN
+GrBackendRenderTarget::GrBackendRenderTarget(int width,
+ int height,
+ int sampleCnt,
+ int stencilBits,
+ const GrDawnImageInfo& dawnInfo)
+ : fIsValid(true)
+ , fWidth(width)
+ , fHeight(height)
+ , fSampleCnt(sampleCnt)
+ , fStencilBits(stencilBits)
+ , fConfig(GrDawnFormatToPixelConfig(dawnInfo.fFormat))
+ , fBackend(GrBackendApi::kDawn)
+ , fDawnInfo(dawnInfo) {}
+#endif
+
GrBackendRenderTarget::GrBackendRenderTarget(int width,
int height,
int sampleCnt,
@@ -670,6 +754,11 @@
fVkInfo.assign(that.fVkInfo, this->isValid());
#endif
break;
+#ifdef SK_DAWN
+ case GrBackendApi::kDawn:
+ fDawnInfo = that.fDawnInfo;
+ break;
+#endif
#ifdef SK_METAL
case GrBackendApi::kMetal:
fMtlInfo = that.fMtlInfo;
@@ -685,6 +774,16 @@
return *this;
}
+#ifdef SK_DAWN
+bool GrBackendRenderTarget::getDawnImageInfo(GrDawnImageInfo* outInfo) const {
+ if (this->isValid() && GrBackendApi::kDawn == fBackend) {
+ *outInfo = fDawnInfo;
+ return true;
+ }
+ return false;
+}
+#endif
+
bool GrBackendRenderTarget::getVkImageInfo(GrVkImageInfo* outInfo) const {
#ifdef SK_VULKAN
if (this->isValid() && GrBackendApi::kVulkan == fBackend) {
@@ -802,6 +901,10 @@
case GrBackendApi::kMetal:
return r0.fMtlInfo == r1.fMtlInfo;
#endif
+#ifdef SK_DAWN
+ case GrBackendApi::kDawn:
+ return r0.fDawnInfo == r1.fDawnInfo;
+#endif
default:
return false;
}
diff --git a/src/gpu/GrContextPriv.cpp b/src/gpu/GrContextPriv.cpp
index ad6d8ab..14795d2 100644
--- a/src/gpu/GrContextPriv.cpp
+++ b/src/gpu/GrContextPriv.cpp
@@ -231,14 +231,16 @@
static const char* kBackendStr[] = {
"Metal",
+ "Dawn",
"OpenGL",
"Vulkan",
"Mock",
};
GR_STATIC_ASSERT(0 == (unsigned)GrBackendApi::kMetal);
- GR_STATIC_ASSERT(1 == (unsigned)GrBackendApi::kOpenGL);
- GR_STATIC_ASSERT(2 == (unsigned)GrBackendApi::kVulkan);
- GR_STATIC_ASSERT(3 == (unsigned)GrBackendApi::kMock);
+ GR_STATIC_ASSERT(1 == (unsigned)GrBackendApi::kDawn);
+ GR_STATIC_ASSERT(2 == (unsigned)GrBackendApi::kOpenGL);
+ GR_STATIC_ASSERT(3 == (unsigned)GrBackendApi::kVulkan);
+ GR_STATIC_ASSERT(4 == (unsigned)GrBackendApi::kMock);
writer.appendString("backend", kBackendStr[(unsigned)fContext->backend()]);
writer.appendName("caps");
diff --git a/src/gpu/GrLegacyDirectContext.cpp b/src/gpu/GrLegacyDirectContext.cpp
index 4c3f756..b6bfd12 100644
--- a/src/gpu/GrLegacyDirectContext.cpp
+++ b/src/gpu/GrLegacyDirectContext.cpp
@@ -23,6 +23,9 @@
#ifdef SK_VULKAN
#include "src/gpu/vk/GrVkGpu.h"
#endif
+#ifdef SK_DAWN
+#include "dawn/GrDawnGpu.h"
+#endif
#ifdef SK_DISABLE_REDUCE_OPLIST_SPLITTING
static const bool kDefaultReduceOpListSplitting = false;
@@ -218,3 +221,23 @@
}
#endif
+#ifdef SK_DAWN
+sk_sp<GrContext> GrContext::MakeDawn(const dawn::Device& device) {
+ GrContextOptions defaultOptions;
+ return MakeDawn(device, defaultOptions);
+}
+
+sk_sp<GrContext> GrContext::MakeDawn(const dawn::Device& device, const GrContextOptions& options) {
+ sk_sp<GrContext> context(new GrLegacyDirectContext(GrBackendApi::kDawn, options));
+
+ context->fGpu = GrDawnGpu::Make(device, options, context.get());
+ if (!context->fGpu) {
+ return nullptr;
+ }
+
+ if (!context->init(context->fGpu->refCaps(), nullptr)) {
+ return nullptr;
+ }
+ return context;
+}
+#endif
diff --git a/src/gpu/dawn/GrDawnCaps.cpp b/src/gpu/dawn/GrDawnCaps.cpp
new file mode 100644
index 0000000..3fb9a55
--- /dev/null
+++ b/src/gpu/dawn/GrDawnCaps.cpp
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrDawnCaps.h"
+
+GrDawnCaps::GrDawnCaps(const GrContextOptions& contextOptions) : INHERITED(contextOptions) {
+ fBufferMapThreshold = SK_MaxS32; // FIXME: get this from Dawn?
+ fShaderCaps.reset(new GrShaderCaps(contextOptions));
+ fMaxTextureSize = 2048;
+ fPerformPartialClearsAsDraws = true;
+}
+
+bool GrDawnCaps::isFormatSRGB(const GrBackendFormat& format) const {
+ return false;
+}
+
+bool GrDawnCaps::isConfigTexturable(GrPixelConfig config) const {
+ switch (config) {
+ case kRGBA_8888_GrPixelConfig:
+ case kBGRA_8888_GrPixelConfig:
+ case kAlpha_8_GrPixelConfig:
+ return true;
+ default:
+ return false;
+ }
+}
+
+GrPixelConfig GrDawnCaps::onGetConfigFromBackendFormat(const GrBackendFormat& format,
+ GrColorType colorType) const {
+ dawn::TextureFormat textureFormat = *format.getDawnFormat();
+ switch (colorType) {
+ case GrColorType::kUnknown:
+ return kUnknown_GrPixelConfig;
+ case GrColorType::kAlpha_8:
+ if (dawn::TextureFormat::R8Unorm == textureFormat) {
+ return kAlpha_8_as_Red_GrPixelConfig;
+ }
+ break;
+ case GrColorType::kRGBA_8888:
+ if (dawn::TextureFormat::R8G8B8A8Unorm == textureFormat) {
+ return kRGBA_8888_GrPixelConfig;
+ }
+ break;
+ case GrColorType::kRGB_888x:
+ break;
+ case GrColorType::kBGRA_8888:
+ if (dawn::TextureFormat::B8G8R8A8Unorm == textureFormat) {
+ return kBGRA_8888_GrPixelConfig;
+ }
+ break;
+ default:
+ break;
+ }
+ return kUnknown_GrPixelConfig;
+}
+
+GrPixelConfig GrDawnCaps::getYUVAConfigFromBackendFormat(const GrBackendFormat& backendFormat)
+ const {
+ const dawn::TextureFormat* format = backendFormat.getDawnFormat();
+ if (!format) {
+ return kUnknown_GrPixelConfig;
+ }
+ switch (*format) {
+ case dawn::TextureFormat::R8Unorm:
+ return kAlpha_8_as_Red_GrPixelConfig;
+ break;
+ case dawn::TextureFormat::R8G8B8A8Unorm:
+ return kRGBA_8888_GrPixelConfig;
+ break;
+ case dawn::TextureFormat::B8G8R8A8Unorm:
+ return kBGRA_8888_GrPixelConfig;
+ break;
+ default:
+ return kUnknown_GrPixelConfig;
+ break;
+ }
+}
+
+size_t GrDawnCaps::onTransferFromOffsetAlignment(GrColorType bufferColorType) const {
+ if (bufferColorType == GrColorType::kRGB_888x) {
+ return false;
+ }
+ size_t bpp = GrColorTypeBytesPerPixel(bufferColorType);
+ switch (bpp & 0b11) {
+ case 0: return bpp;
+ case 2: return 2 * bpp;
+ default: return 4 * bpp;
+ }
+}
+
+static GrSwizzle get_swizzle(const GrBackendFormat& format, GrColorType colorType,
+ bool forOutput) {
+ SkASSERT(format.getDawnFormat());
+
+ switch (colorType) {
+ case GrColorType::kAlpha_8: // fall through
+ case GrColorType::kAlpha_F16:
+ if (forOutput) {
+ return GrSwizzle::AAAA();
+ } else {
+ return GrSwizzle::RRRR();
+ }
+ case GrColorType::kGray_8:
+ if (!forOutput) {
+ return GrSwizzle::RRRA();
+ }
+ break;
+ case GrColorType::kRGB_888x:
+ if (!forOutput) {
+ return GrSwizzle::RGB1();
+ }
+ default:
+ return GrSwizzle::RGBA();
+ }
+ return GrSwizzle::RGBA();
+}
+
+bool GrDawnCaps::isFormatTexturable(GrColorType ct, const GrBackendFormat& format) const {
+ GrPixelConfig config = this->getConfigFromBackendFormat(format, ct);
+ if (kUnknown_GrPixelConfig == config) {
+ return false;
+ }
+
+ return this->isConfigTexturable(config);
+}
+
+bool GrDawnCaps::isFormatCopyable(GrColorType ct, const GrBackendFormat& format) const {
+ return true;
+}
+
+int GrDawnCaps::getRenderTargetSampleCount(int requestedCount, GrColorType ct,
+ const GrBackendFormat& format) const {
+ GrPixelConfig config = this->getConfigFromBackendFormat(format, ct);
+ if (kUnknown_GrPixelConfig == config) {
+ return 0;
+ }
+
+ return this->getRenderTargetSampleCount(requestedCount, config);
+}
+
+GrBackendFormat GrDawnCaps::getBackendFormatFromColorType(GrColorType ct) const {
+ GrPixelConfig config = GrColorTypeToPixelConfig(ct);
+ if (config == kUnknown_GrPixelConfig) {
+ return GrBackendFormat();
+ }
+ dawn::TextureFormat format;
+ if (!GrPixelConfigToDawnFormat(config, &format)) {
+ return GrBackendFormat();
+ }
+ return GrBackendFormat::MakeDawn(format);
+}
+
+GrBackendFormat GrDawnCaps::getBackendFormatFromCompressionType(SkImage::CompressionType type) const
+{
+ return GrBackendFormat();
+}
+
+GrSwizzle GrDawnCaps::getTextureSwizzle(const GrBackendFormat& format, GrColorType colorType) const
+{
+ return get_swizzle(format, colorType, false);
+}
+
+bool GrDawnCaps::canClearTextureOnCreation() const {
+ return true;
+}
+
+GrSwizzle GrDawnCaps::getOutputSwizzle(const GrBackendFormat& format, GrColorType colorType) const
+{
+ return get_swizzle(format, colorType, true);
+}
+
+bool GrDawnCaps::onAreColorTypeAndFormatCompatible(GrColorType ct,
+ const GrBackendFormat& format) const {
+ return true;
+}
diff --git a/src/gpu/dawn/GrDawnCaps.h b/src/gpu/dawn/GrDawnCaps.h
new file mode 100644
index 0000000..a28eae0
--- /dev/null
+++ b/src/gpu/dawn/GrDawnCaps.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrDawnCaps_DEFINED
+#define GrDawnCaps_DEFINED
+
+#include "src/gpu/GrCaps.h"
+#include "include/gpu/GrContextOptions.h"
+#include "src/gpu/dawn/GrDawnUtil.h"
+#include "include/gpu/GrBackendSurface.h"
+
+class GrDawnCaps : public GrCaps {
+public:
+ GrDawnCaps(const GrContextOptions& contextOptions);
+
+ bool isFormatSRGB(const GrBackendFormat& format) const override;
+ bool isFormatTexturable(GrColorType, const GrBackendFormat& format) const override;
+ bool isFormatCopyable(GrColorType, const GrBackendFormat& format) const override;
+
+ bool isConfigTexturable(GrPixelConfig config) const override;
+
+ bool isConfigCopyable(GrPixelConfig config) const override {
+ return true;
+ }
+
+ bool onCanCopySurface(const GrSurfaceProxy* dst, const GrSurfaceProxy* src,
+ const SkIRect& srcRect, const SkIPoint& dstPoint) const override {
+ return true;
+ }
+
+ bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
+ bool* rectsMustMatch, bool* disallowSubrect) const override {
+ return false;
+ }
+
+ GrPixelConfig validateBackendRenderTarget(const GrBackendRenderTarget&, GrColorType) const
+ override {
+ return GrPixelConfig::kUnknown_GrPixelConfig;
+ }
+
+ GrPixelConfig onGetConfigFromBackendFormat(const GrBackendFormat&, GrColorType) const override;
+
+ GrPixelConfig getYUVAConfigFromBackendFormat(const GrBackendFormat&) const override;
+
+ SurfaceReadPixelsSupport surfaceSupportsReadPixels(const GrSurface*) const override {
+ return SurfaceReadPixelsSupport::kSupported;
+ }
+
+ bool onSurfaceSupportsWritePixels(const GrSurface* surface) const override {
+ return true;
+ }
+
+ int getRenderTargetSampleCount(int requestedCount, GrColorType,
+ const GrBackendFormat&) const override;
+
+ int getRenderTargetSampleCount(int requestedCount, GrPixelConfig config) const override {
+ return this->isConfigTexturable(config) ? 1 : 0;
+ }
+
+ int maxRenderTargetSampleCount(GrColorType ct,
+ const GrBackendFormat& format) const override {
+ return this->maxRenderTargetSampleCount(this->getConfigFromBackendFormat(format, ct));
+ }
+
+ int maxRenderTargetSampleCount(GrPixelConfig config) const override {
+ return this->isConfigTexturable(config) ? 1 : 0;
+ }
+
+ GrBackendFormat getBackendFormatFromColorType(GrColorType ct) const override;
+
+ GrBackendFormat getBackendFormatFromCompressionType(SkImage::CompressionType) const override;
+
+ bool canClearTextureOnCreation() const override;
+
+ GrSwizzle getTextureSwizzle(const GrBackendFormat&, GrColorType) const override;
+
+ GrSwizzle getOutputSwizzle(const GrBackendFormat&, GrColorType) const override;
+
+ size_t onTransferFromOffsetAlignment(GrColorType bufferColorType) const override;
+
+ bool onAreColorTypeAndFormatCompatible(GrColorType, const GrBackendFormat&) const override;
+
+ typedef GrCaps INHERITED;
+};
+
+#endif
diff --git a/src/gpu/dawn/GrDawnGpu.cpp b/src/gpu/dawn/GrDawnGpu.cpp
new file mode 100644
index 0000000..b3d4a97
--- /dev/null
+++ b/src/gpu/dawn/GrDawnGpu.cpp
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrDawnGpu.h"
+
+#include "include/gpu/GrBackendSemaphore.h"
+#include "include/gpu/GrBackendSurface.h"
+#include "include/gpu/GrContextOptions.h"
+#include "src/gpu/GrGeometryProcessor.h"
+#include "src/gpu/GrGpuResourceCacheAccess.h"
+#include "src/gpu/GrMesh.h"
+#include "src/gpu/dawn/GrDawnCaps.h"
+#include "src/gpu/dawn/GrDawnRenderTarget.h"
+#include "src/gpu/dawn/GrDawnGpuCommandBuffer.h"
+#include "src/gpu/GrPipeline.h"
+#include "src/gpu/GrRenderTargetPriv.h"
+#include "src/gpu/GrSemaphore.h"
+#include "src/gpu/GrTexturePriv.h"
+
+#include "src/sksl/SkSLCompiler.h"
+
+#if !defined(SK_BUILD_FOR_WIN)
+#include <unistd.h>
+#endif // !defined(SK_BUILD_FOR_WIN)
+
+sk_sp<GrGpu> GrDawnGpu::Make(const dawn::Device& device,
+ const GrContextOptions& options, GrContext* context) {
+ if (!device) {
+ return nullptr;
+ }
+
+ return sk_sp<GrGpu>(new GrDawnGpu(context, options, device));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+GrDawnGpu::GrDawnGpu(GrContext* context, const GrContextOptions& options,
+ const dawn::Device& device)
+ : INHERITED(context)
+ , fDevice(device)
+ , fQueue(device.CreateQueue())
+ , fCompiler(new SkSL::Compiler()) {
+ fCaps.reset(new GrDawnCaps(options));
+}
+
+GrDawnGpu::~GrDawnGpu() {
+}
+
+
+void GrDawnGpu::disconnect(DisconnectType type) {
+ INHERITED::disconnect(type);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+GrGpuRTCommandBuffer* GrDawnGpu::getCommandBuffer(
+ GrRenderTarget* rt, GrSurfaceOrigin origin, const SkRect& bounds,
+ const GrGpuRTCommandBuffer::LoadAndStoreInfo& colorInfo,
+ const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo& stencilInfo) {
+ fCachedRTCommandBuffer.reset(
+ new GrDawnGpuRTCommandBuffer(this, rt, origin, colorInfo, stencilInfo));
+ return fCachedRTCommandBuffer.get();
+}
+
+GrGpuTextureCommandBuffer* GrDawnGpu::getCommandBuffer(GrTexture* texture,
+ GrSurfaceOrigin origin) {
+ return nullptr;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+sk_sp<GrGpuBuffer> GrDawnGpu::onCreateBuffer(size_t size, GrGpuBufferType type,
+ GrAccessPattern accessPattern, const void* data) {
+ return nullptr;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+bool GrDawnGpu::onWritePixels(GrSurface* surface,
+ int left, int top, int width, int height,
+ GrColorType colorType,
+ const GrMipLevel texels[], int mipLevelCount) {
+ return false;
+}
+
+bool GrDawnGpu::onTransferPixelsTo(GrTexture* texture,
+ int left, int top, int width, int height,
+ GrColorType colorType, GrGpuBuffer* transferBuffer,
+ size_t bufferOffset, size_t rowBytes) {
+ return false;
+}
+
+bool GrDawnGpu::onTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
+ GrColorType, GrGpuBuffer* transferBuffer, size_t offset) {
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+sk_sp<GrTexture> GrDawnGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
+ const GrMipLevel texels[], int mipLevelCount) {
+ return nullptr;
+}
+
+sk_sp<GrTexture> GrDawnGpu::onCreateCompressedTexture(int width, int height,
+ SkImage::CompressionType, SkBudgeted,
+ const void* data) {
+ return nullptr;
+}
+
+sk_sp<GrTexture> GrDawnGpu::onWrapBackendTexture(const GrBackendTexture& backendTex,
+ GrWrapOwnership ownership,
+ GrWrapCacheable cacheable,
+ GrIOType) {
+ return nullptr;
+}
+
+sk_sp<GrTexture> GrDawnGpu::onWrapRenderableBackendTexture(const GrBackendTexture& tex,
+ int sampleCnt, GrColorType,
+ GrWrapOwnership,
+ GrWrapCacheable cacheable) {
+ return nullptr;
+}
+
+sk_sp<GrRenderTarget> GrDawnGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget&) {
+ return nullptr;
+}
+
+sk_sp<GrRenderTarget> GrDawnGpu::onWrapBackendTextureAsRenderTarget(const GrBackendTexture& tex,
+ int sampleCnt) {
+ GrDawnImageInfo info;
+ if (!tex.getDawnImageInfo(&info)) {
+ return nullptr;
+ }
+ if (!info.fTexture) {
+ return nullptr;
+ }
+
+ GrSurfaceDesc desc;
+ desc.fFlags = kRenderTarget_GrSurfaceFlag;
+ desc.fWidth = tex.width();
+ desc.fHeight = tex.height();
+ desc.fConfig = tex.config();
+ desc.fSampleCnt = this->caps()->getRenderTargetSampleCount(sampleCnt, tex.config());
+ if (desc.fSampleCnt < 1) {
+ return nullptr;
+ }
+
+ sk_sp<GrDawnRenderTarget> tgt = GrDawnRenderTarget::MakeWrapped(this, desc, info);
+ return tgt;
+}
+
+GrStencilAttachment* GrDawnGpu::createStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
+ int width,
+ int height,
+ int numStencilSamples) {
+ return nullptr;
+}
+
+GrBackendTexture GrDawnGpu::createBackendTexture(int width, int height,
+ const GrBackendFormat& format,
+ GrMipMapped mipMapped,
+ GrRenderable renderable,
+ const void* pixels,
+ size_t rowBytes,
+ const SkColor4f* color,
+ GrProtected isProtected) {
+ return GrBackendTexture();
+}
+
+void GrDawnGpu::deleteBackendTexture(const GrBackendTexture& tex) {
+}
+
+#if GR_TEST_UTILS
+bool GrDawnGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
+ return false;
+}
+
+GrBackendRenderTarget GrDawnGpu::createTestingOnlyBackendRenderTarget(int w, int h, GrColorType) {
+ return GrBackendRenderTarget();
+}
+
+void GrDawnGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) {
+}
+
+void GrDawnGpu::testingOnly_flushGpuAndSync() {
+}
+
+#endif
+
+void GrDawnGpu::onFinishFlush(GrSurfaceProxy*[], int n, SkSurface::BackendSurfaceAccess access,
+ const GrFlushInfo& info, const GrPrepareForExternalIORequests&) {
+}
+
+bool GrDawnGpu::onCopySurface(GrSurface* dst,
+ GrSurface* src,
+ const SkIRect& srcRect,
+ const SkIPoint& dstPoint,
+ bool canDiscardOutsideDstRect) {
+ return false;
+}
+
+bool GrDawnGpu::onReadPixels(GrSurface* surface,
+ int left, int top, int width, int height,
+ GrColorType colorType,
+ void* buffer,
+ size_t rowBytes) {
+ return false;
+}
+
+bool GrDawnGpu::onRegenerateMipMapLevels(GrTexture*) {
+ return false;
+}
+
+void GrDawnGpu::submit(GrGpuCommandBuffer* buffer) {
+ if (auto buf = static_cast<GrDawnGpuRTCommandBuffer*>(buffer->asRTCommandBuffer())) {
+ buf->submit();
+ }
+}
+
+GrFence SK_WARN_UNUSED_RESULT GrDawnGpu::insertFence() {
+ return GrFence();
+}
+
+bool GrDawnGpu::waitFence(GrFence fence, uint64_t timeout) {
+ return false;
+}
+
+void GrDawnGpu::deleteFence(GrFence fence) const {
+}
+
+sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT GrDawnGpu::makeSemaphore(bool isOwned) {
+ return nullptr;
+}
+
+sk_sp<GrSemaphore> GrDawnGpu::wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
+ GrResourceProvider::SemaphoreWrapType wrapType,
+ GrWrapOwnership ownership) {
+ SkASSERT(!"unimplemented");
+ return nullptr;
+}
+
+void GrDawnGpu::insertSemaphore(sk_sp<GrSemaphore> semaphore) {
+ SkASSERT(!"unimplemented");
+}
+
+void GrDawnGpu::waitSemaphore(sk_sp<GrSemaphore> semaphore) {
+ SkASSERT(!"unimplemented");
+}
+
+void GrDawnGpu::checkFinishProcs() {
+ SkASSERT(!"unimplemented");
+}
+
+sk_sp<GrSemaphore> GrDawnGpu::prepareTextureForCrossContextUsage(GrTexture* texture) {
+ return nullptr;
+}
diff --git a/src/gpu/dawn/GrDawnGpu.h b/src/gpu/dawn/GrDawnGpu.h
new file mode 100644
index 0000000..e3c428f
--- /dev/null
+++ b/src/gpu/dawn/GrDawnGpu.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrDawnGpu_DEFINED
+#define GrDawnGpu_DEFINED
+
+#include "src/gpu/GrGpu.h"
+#include "dawn/dawncpp.h"
+
+class GrPipeline;
+class GrDawnGpuRTCommandBuffer;
+
+namespace SkSL {
+ class Compiler;
+}
+
+class GrDawnGpu : public GrGpu {
+public:
+ static sk_sp<GrGpu> Make(const dawn::Device& device, const GrContextOptions&, GrContext*);
+ GrDawnGpu(GrContext* context, const GrContextOptions& options, const dawn::Device& device);
+
+ ~GrDawnGpu() override;
+
+ void disconnect(DisconnectType) override;
+
+ const dawn::Device& device() const { return fDevice; }
+ const dawn::Queue& queue() const { return fQueue; }
+
+ void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {}
+
+ GrBackendTexture createBackendTexture(int w, int h,
+ const GrBackendFormat &,
+ GrMipMapped,
+ GrRenderable,
+ const void* pixels,
+ size_t rowBytes,
+ const SkColor4f* color,
+ GrProtected isProtected) override;
+ void deleteBackendTexture(const GrBackendTexture&) override;
+#if GR_TEST_UTILS
+ bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override;
+
+ GrBackendRenderTarget createTestingOnlyBackendRenderTarget(int w, int h, GrColorType) override;
+ void deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) override;
+
+ void testingOnly_flushGpuAndSync() override;
+#endif
+
+ GrStencilAttachment* createStencilAttachmentForRenderTarget(const GrRenderTarget*,
+ int width,
+ int height,
+ int numStencilSamples) override;
+
+ GrGpuRTCommandBuffer* getCommandBuffer(
+ GrRenderTarget*, GrSurfaceOrigin, const SkRect& bounds,
+ const GrGpuRTCommandBuffer::LoadAndStoreInfo&,
+ const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo&) override;
+
+ GrGpuTextureCommandBuffer* getCommandBuffer(GrTexture*, GrSurfaceOrigin) override;
+
+ SkSL::Compiler* shaderCompiler() const {
+ return fCompiler.get();
+ }
+
+ void submit(GrGpuCommandBuffer* cb) override;
+ GrFence SK_WARN_UNUSED_RESULT insertFence() override;
+ bool waitFence(GrFence, uint64_t timeout) override;
+ void deleteFence(GrFence) const override;
+
+ sk_sp<GrSemaphore> SK_WARN_UNUSED_RESULT makeSemaphore(bool isOwned = true) override;
+ sk_sp<GrSemaphore> wrapBackendSemaphore(const GrBackendSemaphore& semaphore,
+ GrResourceProvider::SemaphoreWrapType wrapType,
+ GrWrapOwnership ownership) override;
+ void insertSemaphore(sk_sp<GrSemaphore> semaphore) override;
+ void waitSemaphore(sk_sp<GrSemaphore> semaphore) override;
+ void checkFinishProcs() override;
+
+ sk_sp<GrSemaphore> prepareTextureForCrossContextUsage(GrTexture*) override;
+
+private:
+ void onResetContext(uint32_t resetBits) override {}
+
+ virtual void querySampleLocations(GrRenderTarget*, SkTArray<SkPoint>*) override {}
+
+ sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
+ const GrMipLevel texels[], int mipLevelCount) override;
+
+ sk_sp<GrTexture> onCreateCompressedTexture(int width, int height, SkImage::CompressionType,
+ SkBudgeted, const void* data) override;
+
+ sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership,
+ GrWrapCacheable, GrIOType) override;
+ sk_sp<GrTexture> onWrapRenderableBackendTexture(const GrBackendTexture&, int sampleCnt,
+ GrColorType, GrWrapOwnership,
+ GrWrapCacheable) override;
+ sk_sp<GrRenderTarget> onWrapBackendRenderTarget(const GrBackendRenderTarget&) override;
+
+ sk_sp<GrRenderTarget> onWrapBackendTextureAsRenderTarget(const GrBackendTexture&,
+ int sampleCnt) override;
+
+ sk_sp<GrGpuBuffer> onCreateBuffer(size_t size, GrGpuBufferType type, GrAccessPattern,
+ const void* data) override;
+
+ bool onReadPixels(GrSurface* surface,
+ int left, int top, int width, int height,
+ GrColorType, void* buffer, size_t rowBytes) override;
+
+ bool onWritePixels(GrSurface* surface,
+ int left, int top, int width, int height,
+ GrColorType, const GrMipLevel texels[], int mipLevelCount) override;
+
+ bool onTransferPixelsTo(GrTexture*, int left, int top, int width, int height,
+ GrColorType colorType, GrGpuBuffer* transferBuffer,
+ size_t offset, size_t rowBytes) override;
+
+ bool onTransferPixelsFrom(GrSurface* surface, int left, int top, int width, int height,
+ GrColorType, GrGpuBuffer* transferBuffer, size_t offset) override;
+
+ void onResolveRenderTarget(GrRenderTarget* target) override {
+ }
+
+ bool onRegenerateMipMapLevels(GrTexture*) override;
+
+ bool onCopySurface(GrSurface* dst, GrSurface* src,
+ const SkIRect& srcRect, const SkIPoint& dstPoint,
+ bool canDiscardOutsideDstRect) override;
+
+ void onFinishFlush(GrSurfaceProxy*[], int n, SkSurface::BackendSurfaceAccess access,
+ const GrFlushInfo& info, const GrPrepareForExternalIORequests&) override;
+
+ dawn::Device fDevice;
+ dawn::Queue fQueue; // Must be Graphics queue
+
+ // Compiler used for compiling sksl into spirv. We only want to create the compiler once since
+ // there is significant overhead to the first compile of any compiler.
+ std::unique_ptr<SkSL::Compiler> fCompiler;
+
+ std::unique_ptr<GrDawnGpuRTCommandBuffer> fCachedRTCommandBuffer;
+
+ typedef GrGpu INHERITED;
+};
+
+#endif
diff --git a/src/gpu/dawn/GrDawnGpuCommandBuffer.cpp b/src/gpu/dawn/GrDawnGpuCommandBuffer.cpp
new file mode 100644
index 0000000..39e3169
--- /dev/null
+++ b/src/gpu/dawn/GrDawnGpuCommandBuffer.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrDawnGpuCommandBuffer.h"
+
+#include "src/gpu/GrFixedClip.h"
+#include "src/gpu/GrMesh.h"
+#include "src/gpu/GrOpFlushState.h"
+#include "src/gpu/GrPipeline.h"
+#include "src/gpu/GrRenderTargetPriv.h"
+#include "src/gpu/GrTexturePriv.h"
+#include "src/gpu/dawn/GrDawnGpu.h"
+#include "src/gpu/dawn/GrDawnRenderTarget.h"
+#include "include/core/SkRect.h"
+
+void GrDawnGpuTextureCommandBuffer::copy(GrSurface* src, const SkIRect& srcRect,
+ const SkIPoint& dstPoint) {
+}
+
+void GrDawnGpuTextureCommandBuffer::insertEventMarker(const char* msg) {
+}
+
+void GrDawnGpuTextureCommandBuffer::submit() {
+ for (int i = 0; i < fCopies.count(); ++i) {
+ CopyInfo& copyInfo = fCopies[i];
+ fGpu->copySurface(fTexture, copyInfo.fSrc, copyInfo.fSrcRect, copyInfo.fDstPoint);
+ }
+}
+
+GrDawnGpuTextureCommandBuffer::~GrDawnGpuTextureCommandBuffer() {}
+
+////////////////////////////////////////////////////////////////////////////////
+
+dawn::LoadOp to_dawn_load_op(GrLoadOp loadOp) {
+ switch (loadOp) {
+ case GrLoadOp::kLoad:
+ return dawn::LoadOp::Load;
+ case GrLoadOp::kClear:
+ return dawn::LoadOp::Clear;
+ case GrLoadOp::kDiscard:
+ default:
+ SK_ABORT("Invalid LoadOp");
+ return dawn::LoadOp::Load;
+ }
+}
+
+GrDawnGpuRTCommandBuffer::GrDawnGpuRTCommandBuffer(GrDawnGpu* gpu,
+ GrRenderTarget* rt, GrSurfaceOrigin origin,
+ const LoadAndStoreInfo& colorInfo,
+ const StencilLoadAndStoreInfo& stencilInfo)
+ : INHERITED(rt, origin)
+ , fGpu(gpu) {
+ this->init();
+}
+
+void GrDawnGpuRTCommandBuffer::init() {
+}
+
+
+GrDawnGpuRTCommandBuffer::~GrDawnGpuRTCommandBuffer() {
+}
+
+GrGpu* GrDawnGpuRTCommandBuffer::gpu() { return fGpu; }
+
+void GrDawnGpuRTCommandBuffer::end() {
+}
+
+void GrDawnGpuRTCommandBuffer::submit() {
+ if (fCommandBuffer) {
+ fGpu->queue().Submit(1, &fCommandBuffer);
+ }
+}
+
+void GrDawnGpuRTCommandBuffer::insertEventMarker(const char* msg) {
+}
+
+void GrDawnGpuRTCommandBuffer::transferFrom(const SkIRect& srcRect, GrColorType bufferColorType,
+ GrGpuBuffer* transferBuffer, size_t offset) {
+ fGpu->transferPixelsFrom(fRenderTarget, srcRect.fLeft, srcRect.fTop, srcRect.width(),
+ srcRect.height(), bufferColorType, transferBuffer, offset);
+}
+
+void GrDawnGpuRTCommandBuffer::onClearStencilClip(const GrFixedClip& clip, bool insideStencilMask) {
+}
+
+void GrDawnGpuRTCommandBuffer::onClear(const GrFixedClip& clip, const SkPMColor4f& color) {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void GrDawnGpuRTCommandBuffer::inlineUpload(GrOpFlushState* state,
+ GrDeferredTextureUploadFn& upload) {
+}
+
+void GrDawnGpuRTCommandBuffer::copy(GrSurface* src, const SkIRect& srcRect,
+ const SkIPoint& dstPoint) {
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void GrDawnGpuRTCommandBuffer::bindGeometry(const GrBuffer* indexBuffer,
+ const GrBuffer* vertexBuffer,
+ const GrBuffer* instanceBuffer) {
+}
+
+void GrDawnGpuRTCommandBuffer::onDraw(const GrPrimitiveProcessor& primProc,
+ const GrPipeline& pipeline,
+ const GrPipeline::FixedDynamicState* fixedDynamicState,
+ const GrPipeline::DynamicStateArrays* dynamicStateArrays,
+ const GrMesh meshes[],
+ int meshCount,
+ const SkRect& bounds) {
+ if (!meshCount) {
+ return;
+ }
+ GrFragmentProcessor::Iter iter(pipeline);
+
+ for (int i = 0; i < meshCount; ++i) {
+ const GrMesh& mesh = meshes[i];
+ mesh.sendToGpu(this);
+ }
+}
+
+void GrDawnGpuRTCommandBuffer::sendInstancedMeshToGpu(GrPrimitiveType,
+ const GrBuffer* vertexBuffer,
+ int vertexCount,
+ int baseVertex,
+ const GrBuffer* instanceBuffer,
+ int instanceCount,
+ int baseInstance) {
+ this->bindGeometry(nullptr, vertexBuffer, instanceBuffer);
+ fGpu->stats()->incNumDraws();
+}
+
+void GrDawnGpuRTCommandBuffer::sendIndexedInstancedMeshToGpu(GrPrimitiveType,
+ const GrBuffer* indexBuffer,
+ int indexCount,
+ int baseIndex,
+ const GrBuffer* vertexBuffer,
+ int baseVertex,
+ const GrBuffer* instanceBuffer,
+ int instanceCount,
+ int baseInstance,
+ GrPrimitiveRestart restart) {
+ this->bindGeometry(indexBuffer, vertexBuffer, instanceBuffer);
+ fGpu->stats()->incNumDraws();
+}
+
diff --git a/src/gpu/dawn/GrDawnGpuCommandBuffer.h b/src/gpu/dawn/GrDawnGpuCommandBuffer.h
new file mode 100644
index 0000000..4a6fd46
--- /dev/null
+++ b/src/gpu/dawn/GrDawnGpuCommandBuffer.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrDawnGpuCommandBuffer_DEFINED
+#define GrDawnGpuCommandBuffer_DEFINED
+
+#include "src/gpu/GrGpuCommandBuffer.h"
+
+#include "src/gpu/GrColor.h"
+#include "src/gpu/GrMesh.h"
+#include "include/gpu/GrTypes.h"
+#include "dawn/dawncpp.h"
+
+class GrDawnGpu;
+class GrDawnRenderTarget;
+
+class GrDawnGpuTextureCommandBuffer : public GrGpuTextureCommandBuffer {
+public:
+ GrDawnGpuTextureCommandBuffer(GrDawnGpu* gpu, GrTexture* texture, GrSurfaceOrigin origin)
+ : INHERITED(texture, origin)
+ , fGpu(gpu) {
+ }
+
+ ~GrDawnGpuTextureCommandBuffer() override;
+
+ void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
+
+ void insertEventMarker(const char*) override;
+
+private:
+ void submit();
+
+ struct CopyInfo {
+ CopyInfo(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect,
+ const SkIPoint& dstPoint)
+ : fSrc(src), fSrcOrigin(srcOrigin), fSrcRect(srcRect), fDstPoint(dstPoint) {}
+
+ GrSurface* fSrc;
+ GrSurfaceOrigin fSrcOrigin;
+ SkIRect fSrcRect;
+ SkIPoint fDstPoint;
+ };
+
+ GrDawnGpu* fGpu;
+ SkTArray<CopyInfo> fCopies;
+
+ typedef GrGpuTextureCommandBuffer INHERITED;
+};
+
+class GrDawnGpuRTCommandBuffer : public GrGpuRTCommandBuffer, private GrMesh::SendToGpuImpl {
+public:
+ GrDawnGpuRTCommandBuffer(GrDawnGpu*, GrRenderTarget*, GrSurfaceOrigin,
+ const LoadAndStoreInfo&,
+ const StencilLoadAndStoreInfo&);
+
+ ~GrDawnGpuRTCommandBuffer() override;
+
+ void begin() override { }
+ void end() override;
+
+ void transferFrom(const SkIRect& srcRect, GrColorType bufferColorType,
+ GrGpuBuffer* transferBuffer, size_t offset) override;
+ void insertEventMarker(const char*) override;
+
+ void inlineUpload(GrOpFlushState* state, GrDeferredTextureUploadFn& upload) override;
+
+ void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
+
+ void submit();
+
+private:
+ void init();
+
+ GrGpu* gpu() override;
+
+ // Bind vertex and index buffers
+ void bindGeometry(const GrBuffer* indexBuffer,
+ const GrBuffer* vertexBuffer,
+ const GrBuffer* instanceBuffer);
+
+ void onDraw(const GrPrimitiveProcessor& primProc,
+ const GrPipeline& pipeline,
+ const GrPipeline::FixedDynamicState* fixedDynamicState,
+ const GrPipeline::DynamicStateArrays* dynamicStateArrays,
+ const GrMesh mesh[],
+ int meshCount,
+ const SkRect& bounds) override;
+
+ void sendMeshToGpu(GrPrimitiveType primType, const GrBuffer* vertexBuffer, int vertexCount,
+ int baseVertex) final {
+ this->sendInstancedMeshToGpu(primType, vertexBuffer, vertexCount, baseVertex,
+ nullptr, 1, 0);
+ }
+
+ void sendIndexedMeshToGpu(GrPrimitiveType primType,
+ const GrBuffer* indexBuffer, int indexCount, int baseIndex,
+ uint16_t /*minIndexValue*/, uint16_t /*maxIndexValue*/,
+ const GrBuffer* vertexBuffer, int baseVertex,
+ GrPrimitiveRestart restart) final {
+ this->sendIndexedInstancedMeshToGpu(primType, indexBuffer, indexCount, baseIndex,
+ vertexBuffer, baseVertex, nullptr, 1, 0, restart);
+ }
+
+ void sendInstancedMeshToGpu(GrPrimitiveType,
+ const GrBuffer* vertexBuffer, int vertexCount, int baseVertex,
+ const GrBuffer* instanceBuffer, int instanceCount,
+ int baseInstance) final;
+
+ void sendIndexedInstancedMeshToGpu(GrPrimitiveType,
+ const GrBuffer* indexBuffer, int indexCount, int baseIndex,
+ const GrBuffer* vertexBuffer, int baseVertex,
+ const GrBuffer* instanceBuffer, int instanceCount,
+ int baseInstance, GrPrimitiveRestart) final;
+
+ void onClear(const GrFixedClip&, const SkPMColor4f& color) override;
+
+ void onClearStencilClip(const GrFixedClip&, bool insideStencilMask) override;
+
+ struct InlineUploadInfo {
+ InlineUploadInfo(GrOpFlushState* state, const GrDeferredTextureUploadFn& upload)
+ : fFlushState(state), fUpload(upload) {}
+
+ GrOpFlushState* fFlushState;
+ GrDeferredTextureUploadFn fUpload;
+ };
+
+ struct CopyInfo {
+ CopyInfo(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect,
+ const SkIPoint& dstPoint)
+ : fSrc(src), fSrcOrigin(srcOrigin), fSrcRect(srcRect), fDstPoint(dstPoint) {}
+
+ GrSurface* fSrc;
+ GrSurfaceOrigin fSrcOrigin;
+ SkIRect fSrcRect;
+ SkIPoint fDstPoint;
+ };
+
+ dawn::CommandBuffer fCommandBuffer;
+ GrDawnGpu* fGpu;
+
+ typedef GrGpuRTCommandBuffer INHERITED;
+};
+
+#endif
diff --git a/src/gpu/dawn/GrDawnRenderTarget.cpp b/src/gpu/dawn/GrDawnRenderTarget.cpp
new file mode 100644
index 0000000..02b8a5b
--- /dev/null
+++ b/src/gpu/dawn/GrDawnRenderTarget.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrDawnRenderTarget.h"
+
+#include "include/gpu/GrBackendSurface.h"
+#include "src/gpu/dawn/GrDawnGpu.h"
+#include "src/gpu/dawn/GrDawnUtil.h"
+
+GrDawnRenderTarget::GrDawnRenderTarget(GrDawnGpu* gpu,
+ const GrSurfaceDesc& desc,
+ const GrDawnImageInfo& info,
+ GrBackendObjectOwnership ownership)
+ : GrSurface(gpu, desc)
+ , GrRenderTarget(gpu, desc)
+ , fInfo(info) {
+ this->registerWithCacheWrapped(GrWrapCacheable::kNo);
+}
+
+GrDawnRenderTarget*
+GrDawnRenderTarget::Create(GrDawnGpu* gpu,
+ const GrSurfaceDesc& desc,
+ const GrDawnImageInfo& info,
+ GrBackendObjectOwnership ownership) {
+ SkASSERT(1 == info.fLevelCount);
+ return new GrDawnRenderTarget(gpu, desc, info, ownership);
+}
+
+sk_sp<GrDawnRenderTarget>
+GrDawnRenderTarget::MakeWrapped(GrDawnGpu* gpu,
+ const GrSurfaceDesc& desc,
+ const GrDawnImageInfo& info) {
+ return sk_sp<GrDawnRenderTarget>(
+ GrDawnRenderTarget::Create(gpu, desc, info,
+ GrBackendObjectOwnership::kBorrowed));
+}
+
+bool GrDawnRenderTarget::completeStencilAttachment() {
+ return true;
+}
+
+GrDawnRenderTarget::~GrDawnRenderTarget() {
+}
+
+void GrDawnRenderTarget::onRelease() {
+ INHERITED::onRelease();
+}
+
+void GrDawnRenderTarget::onAbandon() {
+ INHERITED::onAbandon();
+}
+
+GrBackendRenderTarget GrDawnRenderTarget::getBackendRenderTarget() const {
+ return GrBackendRenderTarget(this->width(), this->height(), this->numSamples(),
+ this->numSamples(), fInfo);
+}
+
+GrBackendFormat GrDawnRenderTarget::backendFormat() const {
+ return GrBackendFormat::MakeDawn(fInfo.fFormat);
+}
diff --git a/src/gpu/dawn/GrDawnRenderTarget.h b/src/gpu/dawn/GrDawnRenderTarget.h
new file mode 100644
index 0000000..271eff0
--- /dev/null
+++ b/src/gpu/dawn/GrDawnRenderTarget.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef GrDawnRenderTarget_DEFINED
+#define GrDawnRenderTarget_DEFINED
+
+#include "include/gpu/dawn/GrDawnTypes.h"
+#include "include/gpu/GrRenderTarget.h"
+
+class GrDawnGpu;
+
+class GrDawnRenderTarget: public GrRenderTarget {
+public:
+ static sk_sp<GrDawnRenderTarget> MakeWrapped(GrDawnGpu*, const GrSurfaceDesc&,
+ const GrDawnImageInfo&);
+
+ ~GrDawnRenderTarget() override;
+
+ // override of GrRenderTarget
+ ResolveType getResolveType() const override {
+ if (this->numSamples() > 1) {
+ return kCanResolve_ResolveType;
+ }
+ return kAutoResolves_ResolveType;
+ }
+
+ bool canAttemptStencilAttachment() const override {
+ return true;
+ }
+
+ GrBackendRenderTarget getBackendRenderTarget() const override;
+ GrBackendFormat backendFormat() const override;
+
+protected:
+ GrDawnRenderTarget(GrDawnGpu* gpu,
+ const GrSurfaceDesc& desc,
+ const GrDawnImageInfo& info,
+ GrBackendObjectOwnership);
+
+ GrDawnGpu* getDawnGpu() const;
+
+ void onAbandon() override;
+ void onRelease() override;
+ void onSetRelease(sk_sp<GrRefCntedCallback> releaseHelper) override {}
+
+ // This accounts for the texture's memory and any MSAA renderbuffer's memory.
+ size_t onGpuMemorySize() const override {
+ // The plus 1 is to account for the resolve texture or if not using msaa the RT itself
+ int numSamples = this->numSamples() + 1;
+ return GrSurface::ComputeSize(this->config(), this->width(), this->height(),
+ numSamples, GrMipMapped::kNo);
+ }
+
+ static GrDawnRenderTarget* Create(GrDawnGpu*, const GrSurfaceDesc&,
+ const GrDawnImageInfo&, GrBackendObjectOwnership);
+
+ bool completeStencilAttachment() override;
+ GrDawnImageInfo fInfo;
+ typedef GrRenderTarget INHERITED;
+};
+
+#endif
diff --git a/src/gpu/dawn/GrDawnUtil.cpp b/src/gpu/dawn/GrDawnUtil.cpp
new file mode 100644
index 0000000..fbb7b43
--- /dev/null
+++ b/src/gpu/dawn/GrDawnUtil.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrDawnUtil.h"
+
+GrPixelConfig GrDawnFormatToPixelConfig(dawn::TextureFormat format) {
+ switch (format) {
+ case dawn::TextureFormat::R8G8B8A8Unorm:
+ return kRGBA_8888_GrPixelConfig;
+ case dawn::TextureFormat::B8G8R8A8Unorm:
+ return kBGRA_8888_GrPixelConfig;
+ case dawn::TextureFormat::R8Unorm:
+ return kAlpha_8_GrPixelConfig;
+ case dawn::TextureFormat::D32FloatS8Uint:
+ default:
+ SkASSERT(false);
+ return kRGBA_8888_GrPixelConfig;
+ }
+}
+
+bool GrPixelConfigToDawnFormat(GrPixelConfig config, dawn::TextureFormat* format) {
+ switch (config) {
+ case kRGBA_8888_GrPixelConfig:
+ case kRGBA_4444_GrPixelConfig:
+ case kRGB_565_GrPixelConfig:
+ case kGray_8_GrPixelConfig:
+ *format = dawn::TextureFormat::R8G8B8A8Unorm;
+ return true;
+ case kBGRA_8888_GrPixelConfig:
+ *format = dawn::TextureFormat::B8G8R8A8Unorm;
+ return true;
+ case kAlpha_8_GrPixelConfig:
+ *format = dawn::TextureFormat::R8Unorm;
+ return true;
+ default:
+ return false;
+ }
+}
diff --git a/src/gpu/dawn/GrDawnUtil.h b/src/gpu/dawn/GrDawnUtil.h
new file mode 100644
index 0000000..6cf973d
--- /dev/null
+++ b/src/gpu/dawn/GrDawnUtil.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrDawnUtil_DEFINED
+#define GrDawnUtil_DEFINED
+
+#include "include/private/GrTypesPriv.h"
+#include "dawn/dawncpp.h"
+
+GrPixelConfig GrDawnFormatToPixelConfig(dawn::TextureFormat format);
+bool GrPixelConfigToDawnFormat(GrPixelConfig config, dawn::TextureFormat* format);
+
+#endif // GrDawnUtil_DEFINED
diff --git a/tools/flags/CommonFlagsConfig.cpp b/tools/flags/CommonFlagsConfig.cpp
index e297feb..1515130 100644
--- a/tools/flags/CommonFlagsConfig.cpp
+++ b/tools/flags/CommonFlagsConfig.cpp
@@ -82,6 +82,9 @@
{ "angle_gl_es3_msaa8", "gpu", "api=angle_gl_es3,samples=8" },
{ "commandbuffer", "gpu", "api=commandbuffer" },
{ "mock", "gpu", "api=mock" },
+#ifdef SK_DAWN
+ { "dawn", "gpu", "api=dawn" },
+#endif
#ifdef SK_VULKAN
{ "vk", "gpu", "api=vulkan" },
{ "vknostencils", "gpu", "api=vulkan,stencils=false" },
@@ -268,6 +271,12 @@
return true;
}
#endif
+#ifdef SK_DAWN
+ if (value.equals("dawn")) {
+ *outContextType = GrContextFactory::kDawn_ContextType;
+ return true;
+ }
+#endif
return false;
}
diff --git a/tools/gpu/GrContextFactory.cpp b/tools/gpu/GrContextFactory.cpp
index e5bea06..d0defdc 100644
--- a/tools/gpu/GrContextFactory.cpp
+++ b/tools/gpu/GrContextFactory.cpp
@@ -20,6 +20,9 @@
#ifdef SK_METAL
#include "tools/gpu/mtl/MtlTestContext.h"
#endif
+#ifdef SK_DAWN
+#include "tools/gpu/dawn/DawnTestContext.h"
+#endif
#include "src/gpu/GrCaps.h"
#include "src/gpu/gl/GrGLGpu.h"
#include "tools/gpu/mock/MockTestContext.h"
@@ -230,6 +233,17 @@
break;
}
#endif
+#ifdef SK_DAWN
+ case GrBackendApi::kDawn: {
+ DawnTestContext* dawnSharedContext = masterContext
+ ? static_cast<DawnTestContext*>(masterContext->fTestContext) : nullptr;
+ testCtx.reset(CreatePlatformDawnTestContext(dawnSharedContext));
+ if (!testCtx) {
+ return ContextInfo();
+ }
+ break;
+ }
+#endif
case GrBackendApi::kMock: {
TestContext* sharedContext = masterContext ? masterContext->fTestContext : nullptr;
SkASSERT(kMock_ContextType == type);
diff --git a/tools/gpu/GrContextFactory.h b/tools/gpu/GrContextFactory.h
index e08dbbd..a85e7ae 100644
--- a/tools/gpu/GrContextFactory.h
+++ b/tools/gpu/GrContextFactory.h
@@ -41,6 +41,7 @@
kCommandBuffer_ContextType, //! Chromium command buffer OpenGL ES context.
kVulkan_ContextType, //! Vulkan
kMetal_ContextType, //! Metal
+ kDawn_ContextType, //! Dawn
kMock_ContextType, //! Mock context that does not draw.
kLastContextType = kMock_ContextType
};
@@ -71,6 +72,8 @@
return GrBackendApi::kVulkan;
case kMetal_ContextType:
return GrBackendApi::kMetal;
+ case kDawn_ContextType:
+ return GrBackendApi::kDawn;
case kMock_ContextType:
return GrBackendApi::kMock;
default:
@@ -100,6 +103,8 @@
return "Vulkan";
case kMetal_ContextType:
return "Metal";
+ case kDawn_ContextType:
+ return "Dawn";
case kMock_ContextType:
return "Mock";
}
diff --git a/tools/gpu/dawn/DawnTestContext.cpp b/tools/gpu/dawn/DawnTestContext.cpp
new file mode 100644
index 0000000..a2fc2d1
--- /dev/null
+++ b/tools/gpu/dawn/DawnTestContext.cpp
@@ -0,0 +1,250 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "dawn/dawncpp.h"
+#include "dawn_native/DawnNative.h"
+#include "DawnTestContext.h"
+
+#ifdef SK_BUILD_FOR_UNIX
+#include "GL/glx.h"
+#endif
+
+#ifdef SK_BUILD_FOR_WIN
+#include <windows.h>
+#endif
+
+#define USE_OPENGL_BACKEND 0
+
+#ifdef SK_DAWN
+#include "dawn/dawn.h"
+#include "include/gpu/GrContext.h"
+#include "tools/AutoreleasePool.h"
+#if USE_OPENGL_BACKEND
+#include "dawn_native/OpenGLBackend.h"
+#endif
+
+#if defined(SK_BUILD_FOR_MAC) && USE_OPENGL_BACKEND
+#include <dlfcn.h>
+static void* getProcAddressMacOS(const char* procName) {
+ return dlsym(RTLD_DEFAULT, procName);
+}
+#endif
+
+namespace {
+
+#ifdef SK_BUILD_FOR_WIN
+class ProcGetter {
+public:
+ typedef void(*Proc)();
+
+ ProcGetter()
+ : fModule(LoadLibraryA("opengl32.dll")) {
+ SkASSERT(!fInstance);
+ fInstance = this;
+ }
+
+ ~ProcGetter() {
+ if (fModule) {
+ FreeLibrary(fModule);
+ }
+ fInstance = nullptr;
+ }
+
+ static void* getProcAddress(const char* name) {
+ return fInstance->getProc(name);
+ }
+
+private:
+ Proc getProc(const char* name) {
+ PROC proc;
+ if (proc = GetProcAddress(fModule, name)) {
+ return (Proc) proc;
+ }
+ if (proc = wglGetProcAddress(name)) {
+ return (Proc) proc;
+ }
+ return nullptr;
+ }
+
+ HMODULE fModule;
+ static ProcGetter* fInstance;
+};
+
+ProcGetter* ProcGetter::fInstance;
+#endif
+
+class DawnFence {
+public:
+ DawnFence(const dawn::Device& device, const dawn::Buffer& buffer)
+ : fDevice(device), fBuffer(buffer), fCalled(false) {
+ fBuffer.MapReadAsync(callback, this);
+ }
+
+ bool wait() {
+ while (!fCalled) {
+ fDevice.Tick();
+ }
+ return true;
+ }
+
+ ~DawnFence() {
+ }
+
+ static void callback(DawnBufferMapAsyncStatus status, const void* data, uint64_t dataLength,
+ void* userData) {
+ DawnFence* fence = static_cast<DawnFence*>(userData);
+ fence->fCalled = true;
+ }
+ dawn::Buffer buffer() { return fBuffer; }
+
+private:
+ dawn::Device fDevice;
+ dawn::Buffer fBuffer;
+ bool fCalled;
+};
+
+/**
+ * Implements sk_gpu_test::FenceSync for Dawn.
+ */
+class DawnFenceSync : public sk_gpu_test::FenceSync {
+public:
+ DawnFenceSync(dawn::Device device) : fDevice(device) {
+ }
+
+ ~DawnFenceSync() override {
+ }
+
+ sk_gpu_test::PlatformFence SK_WARN_UNUSED_RESULT insertFence() const override {
+ dawn::Buffer buffer;
+ if (fBuffers.empty()) {
+ dawn::BufferDescriptor desc;
+ desc.usage = dawn::BufferUsageBit::MapRead | dawn::BufferUsageBit::TransferDst;
+ desc.size = 1;
+ buffer = fDevice.CreateBuffer(&desc);
+ } else {
+ buffer = fBuffers.back();
+ fBuffers.pop_back();
+ }
+ DawnFence* fence = new DawnFence(fDevice, buffer);
+ return reinterpret_cast<sk_gpu_test::PlatformFence>(fence);
+ }
+
+ bool waitFence(sk_gpu_test::PlatformFence opaqueFence) const override {
+ fAutoreleasePool.drain();
+ DawnFence* fence = reinterpret_cast<DawnFence*>(opaqueFence);
+ return fence->wait();
+ }
+
+ void deleteFence(sk_gpu_test::PlatformFence opaqueFence) const override {
+ DawnFence* fence = reinterpret_cast<DawnFence*>(opaqueFence);
+ fBuffers.push_back(fence->buffer());
+ delete fence;
+ }
+
+private:
+ dawn::Device fDevice;
+ mutable std::vector<dawn::Buffer> fBuffers;
+ mutable AutoreleasePool fAutoreleasePool;
+ typedef sk_gpu_test::FenceSync INHERITED;
+};
+
+class DawnTestContextImpl : public sk_gpu_test::DawnTestContext {
+public:
+ static dawn::Device createDevice(const dawn_native::Instance& instance,
+ dawn_native::BackendType type) {
+ DawnProcTable backendProcs = dawn_native::GetProcs();
+ dawnSetProcs(&backendProcs);
+
+ std::vector<dawn_native::Adapter> adapters = instance.GetAdapters();
+ for (dawn_native::Adapter adapter : adapters) {
+ if (adapter.GetBackendType() == type) {
+ return adapter.CreateDevice();
+ }
+ }
+ return nullptr;
+ }
+
+ static DawnTestContext* Create(DawnTestContext* sharedContext) {
+ std::unique_ptr<dawn_native::Instance> instance = std::make_unique<dawn_native::Instance>();
+ dawn::Device device;
+ if (sharedContext) {
+ device = sharedContext->getDevice();
+ } else {
+ dawn_native::BackendType type;
+#if USE_OPENGL_BACKEND
+ dawn_native::opengl::AdapterDiscoveryOptions adapterOptions;
+ adapterOptions.getProc = reinterpret_cast<void*(*)(const char*)>(
+#if defined(SK_BUILD_FOR_UNIX)
+ glXGetProcAddress
+#elif defined(SK_BUILD_FOR_MAC)
+ getProcAddressMacOS
+#elif defined(SK_BUILD_FOR_WIN)
+ ProcGetter::getProcAddress
+#endif
+ );
+ instance->DiscoverAdapters(&adapterOptions);
+ type = dawn_native::BackendType::OpenGL;
+#else
+ instance->DiscoverDefaultAdapters();
+#if defined(SK_BUILD_FOR_MAC)
+ type = dawn_native::BackendType::Metal;
+#elif defined(SK_BUILD_FOR_WIN)
+ type = dawn_native::BackendType::D3D12;
+#elif defined(SK_BUILD_FOR_UNIX)
+ type = dawn_native::BackendType::Vulkan;
+#endif
+#endif
+ device = createDevice(*instance, type);
+ }
+ if (!device) {
+ return nullptr;
+ }
+ return new DawnTestContextImpl(std::move(instance), device);
+ }
+
+ ~DawnTestContextImpl() override { this->teardown(); }
+
+ void testAbandon() override {}
+
+ // There is really nothing to here since we don't own any unqueued command buffers here.
+ void submit() override {}
+
+ void finish() override {}
+
+ sk_sp<GrContext> makeGrContext(const GrContextOptions& options) override {
+ return GrContext::MakeDawn(fDevice, options);
+ }
+
+protected:
+ void teardown() override {
+ INHERITED::teardown();
+ }
+
+private:
+ DawnTestContextImpl(std::unique_ptr<dawn_native::Instance> instance,
+ const dawn::Device& device)
+ : DawnTestContext(device)
+ , fInstance(std::move(instance)) {
+ fFenceSync.reset(new DawnFenceSync(fDevice));
+ }
+
+ void onPlatformMakeCurrent() const override {}
+ std::function<void()> onPlatformGetAutoContextRestore() const override { return nullptr; }
+ void onPlatformSwapBuffers() const override {}
+ std::unique_ptr<dawn_native::Instance> fInstance;
+
+ typedef sk_gpu_test::DawnTestContext INHERITED;
+};
+} // anonymous namespace
+
+namespace sk_gpu_test {
+DawnTestContext* CreatePlatformDawnTestContext(DawnTestContext* sharedContext) {
+ return DawnTestContextImpl::Create(sharedContext);
+}
+} // namespace sk_gpu_test
+
+#endif
diff --git a/tools/gpu/dawn/DawnTestContext.h b/tools/gpu/dawn/DawnTestContext.h
new file mode 100644
index 0000000..4afd018
--- /dev/null
+++ b/tools/gpu/dawn/DawnTestContext.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef DawnTestContext_DEFINED
+#define DawnTestContext_DEFINED
+
+#include "tools/gpu/TestContext.h"
+
+#ifdef SK_DAWN
+
+namespace sk_gpu_test {
+class DawnTestContext : public TestContext {
+public:
+ virtual GrBackend backend() override { return GrBackendApi::kDawn; }
+
+ const dawn::Device& getDevice() {
+ return fDevice;
+ }
+
+protected:
+ DawnTestContext(const dawn::Device& device) : fDevice(device) {}
+
+ dawn::Device fDevice;
+
+private:
+ typedef TestContext INHERITED;
+};
+
+/**
+ * Creates Dawn context object bound to the Dawn library.
+ */
+DawnTestContext* CreatePlatformDawnTestContext(DawnTestContext*);
+
+} // namespace sk_gpu_test
+
+#endif
+
+#endif
diff --git a/tools/sk_app/unix/WindowContextFactory_unix.h b/tools/sk_app/unix/WindowContextFactory_unix.h
index e6d033b..a80f2c9 100644
--- a/tools/sk_app/unix/WindowContextFactory_unix.h
+++ b/tools/sk_app/unix/WindowContextFactory_unix.h
@@ -9,6 +9,10 @@
#ifndef WindowContextFactory_unix_DEFINED
#define WindowContextFactory_unix_DEFINED
+// dawncpp.h and X.h don't get along. Include this first, before X11 defines None, Success etc.
+#ifdef SK_DAWN
+#include "dawn/dawncpp.h"
+#endif
#include <X11/Xlib.h>
#include <GL/glx.h>
typedef Window XWindow;