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 "dawn/webgpu_cpp.h"
9 #include "tools/gpu/dawn/DawnTestContext.h"
10
11 #ifdef SK_BUILD_FOR_UNIX
12 #include "GL/glx.h"
13 #endif
14
15 #ifdef SK_BUILD_FOR_WIN
16 #include <windows.h>
17 #endif
18
19 #define USE_OPENGL_BACKEND 0
20
21 #ifdef SK_DAWN
22 #include "dawn/webgpu.h"
23 #include "dawn/dawn_proc.h"
24 #include "include/gpu/GrDirectContext.h"
25 #include "tools/AutoreleasePool.h"
26 #if USE_OPENGL_BACKEND
27 #include "dawn_native/OpenGLBackend.h"
28 #endif
29
30 #if defined(SK_BUILD_FOR_MAC) && USE_OPENGL_BACKEND
31 #include <dlfcn.h>
getProcAddressMacOS(const char * procName)32 static void* getProcAddressMacOS(const char* procName) {
33 return dlsym(RTLD_DEFAULT, procName);
34 }
35 #endif
36
37 namespace {
38
39 #ifdef SK_BUILD_FOR_WIN
40 class ProcGetter {
41 public:
42 typedef void(*Proc)();
43
ProcGetter()44 ProcGetter()
45 : fModule(LoadLibraryA("opengl32.dll")) {
46 SkASSERT(!fInstance);
47 fInstance = this;
48 }
49
~ProcGetter()50 ~ProcGetter() {
51 if (fModule) {
52 FreeLibrary(fModule);
53 }
54 fInstance = nullptr;
55 }
56
getProcAddress(const char * name)57 static void* getProcAddress(const char* name) {
58 return fInstance->getProc(name);
59 }
60
61 private:
getProc(const char * name)62 Proc getProc(const char* name) {
63 PROC proc;
64 if ((proc = GetProcAddress(fModule, name))) {
65 return (Proc) proc;
66 }
67 if ((proc = wglGetProcAddress(name))) {
68 return (Proc) proc;
69 }
70 return nullptr;
71 }
72
73 HMODULE fModule;
74 static ProcGetter* fInstance;
75 };
76
77 ProcGetter* ProcGetter::fInstance;
78 #endif
79
PrintDeviceError(WGPUErrorType,const char * message,void *)80 static void PrintDeviceError(WGPUErrorType, const char* message, void*) {
81 SkDebugf("Device error: %s\n", message);
82 }
83
84 class DawnTestContextImpl : public sk_gpu_test::DawnTestContext {
85 public:
createDevice(const dawn_native::Instance & instance,wgpu::BackendType type)86 static wgpu::Device createDevice(const dawn_native::Instance& instance,
87 wgpu::BackendType type) {
88 DawnProcTable backendProcs = dawn_native::GetProcs();
89 dawnProcSetProcs(&backendProcs);
90
91 std::vector<dawn_native::Adapter> adapters = instance.GetAdapters();
92 for (dawn_native::Adapter adapter : adapters) {
93 wgpu::AdapterProperties properties;
94 adapter.GetProperties(&properties);
95 if (properties.backendType == type) {
96 return wgpu::Device::Acquire(adapter.CreateDevice());
97 }
98 }
99 return nullptr;
100 }
101
Create(DawnTestContext * sharedContext)102 static DawnTestContext* Create(DawnTestContext* sharedContext) {
103 std::unique_ptr<dawn_native::Instance> instance = std::make_unique<dawn_native::Instance>();
104 wgpu::Device device;
105 if (sharedContext) {
106 device = sharedContext->getDevice();
107 } else {
108 wgpu::BackendType type;
109 #if USE_OPENGL_BACKEND
110 dawn_native::opengl::AdapterDiscoveryOptions adapterOptions;
111 adapterOptions.getProc = reinterpret_cast<void*(*)(const char*)>(
112 #if defined(SK_BUILD_FOR_UNIX)
113 glXGetProcAddress
114 #elif defined(SK_BUILD_FOR_MAC)
115 getProcAddressMacOS
116 #elif defined(SK_BUILD_FOR_WIN)
117 ProcGetter::getProcAddress
118 #endif
119 );
120 instance->DiscoverAdapters(&adapterOptions);
121 type = wgpu::BackendType::OpenGL;
122 #else
123 instance->DiscoverDefaultAdapters();
124 #if defined(SK_BUILD_FOR_MAC)
125 type = wgpu::BackendType::Metal;
126 #elif defined(SK_BUILD_FOR_WIN)
127 type = wgpu::BackendType::D3D12;
128 #elif defined(SK_BUILD_FOR_UNIX)
129 type = wgpu::BackendType::Vulkan;
130 #endif
131 #endif
132 device = createDevice(*instance, type);
133 device.SetUncapturedErrorCallback(PrintDeviceError, 0);
134 }
135 if (!device) {
136 return nullptr;
137 }
138 return new DawnTestContextImpl(std::move(instance), device);
139 }
140
~DawnTestContextImpl()141 ~DawnTestContextImpl() override { this->teardown(); }
142
testAbandon()143 void testAbandon() override {}
144
finish()145 void finish() override {}
146
makeContext(const GrContextOptions & options)147 sk_sp<GrDirectContext> makeContext(const GrContextOptions& options) override {
148 return GrDirectContext::MakeDawn(fDevice, options);
149 }
150
151 protected:
teardown()152 void teardown() override {
153 INHERITED::teardown();
154 }
155
156 private:
DawnTestContextImpl(std::unique_ptr<dawn_native::Instance> instance,const wgpu::Device & device)157 DawnTestContextImpl(std::unique_ptr<dawn_native::Instance> instance,
158 const wgpu::Device& device)
159 : DawnTestContext(std::move(instance), device) {
160 fFenceSupport = true;
161 }
162
onPlatformMakeNotCurrent() const163 void onPlatformMakeNotCurrent() const override {}
onPlatformMakeCurrent() const164 void onPlatformMakeCurrent() const override {}
onPlatformGetAutoContextRestore() const165 std::function<void()> onPlatformGetAutoContextRestore() const override { return nullptr; }
166
167 using INHERITED = sk_gpu_test::DawnTestContext;
168 };
169 } // anonymous namespace
170
171 namespace sk_gpu_test {
CreatePlatformDawnTestContext(DawnTestContext * sharedContext)172 DawnTestContext* CreatePlatformDawnTestContext(DawnTestContext* sharedContext) {
173 return DawnTestContextImpl::Create(sharedContext);
174 }
175 } // namespace sk_gpu_test
176
177 #endif
178