blob: d834a1560a3ac05152b6555c18405d7964f0c2b1 [file] [log] [blame]
Stephen White985741a2019-07-18 11:43:45 -04001/*
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
Stephen Whitea521c962019-12-04 09:57:48 -05008#include "dawn/webgpu_cpp.h"
Stephen White985741a2019-07-18 11:43:45 -04009#include "dawn_native/DawnNative.h"
Mike Klein52337de2019-07-25 09:00:52 -050010#include "tools/gpu/dawn/DawnTestContext.h"
Stephen White985741a2019-07-18 11:43:45 -040011
12#ifdef SK_BUILD_FOR_UNIX
13#include "GL/glx.h"
14#endif
15
16#ifdef SK_BUILD_FOR_WIN
17#include <windows.h>
18#endif
19
20#define USE_OPENGL_BACKEND 0
21
22#ifdef SK_DAWN
Stephen Whitea521c962019-12-04 09:57:48 -050023#include "dawn/webgpu.h"
Stephen White1e2adcf2019-10-16 09:48:53 -040024#include "dawn/dawn_proc.h"
Stephen White985741a2019-07-18 11:43:45 -040025#include "include/gpu/GrContext.h"
26#include "tools/AutoreleasePool.h"
27#if USE_OPENGL_BACKEND
28#include "dawn_native/OpenGLBackend.h"
29#endif
30
31#if defined(SK_BUILD_FOR_MAC) && USE_OPENGL_BACKEND
32#include <dlfcn.h>
33static void* getProcAddressMacOS(const char* procName) {
34 return dlsym(RTLD_DEFAULT, procName);
35}
36#endif
37
38namespace {
39
40#ifdef SK_BUILD_FOR_WIN
41class ProcGetter {
42public:
43 typedef void(*Proc)();
44
45 ProcGetter()
46 : fModule(LoadLibraryA("opengl32.dll")) {
47 SkASSERT(!fInstance);
48 fInstance = this;
49 }
50
51 ~ProcGetter() {
52 if (fModule) {
53 FreeLibrary(fModule);
54 }
55 fInstance = nullptr;
56 }
57
58 static void* getProcAddress(const char* name) {
59 return fInstance->getProc(name);
60 }
61
62private:
63 Proc getProc(const char* name) {
64 PROC proc;
Stephen White883c7e92019-10-17 10:44:37 -040065 if ((proc = GetProcAddress(fModule, name))) {
Stephen White985741a2019-07-18 11:43:45 -040066 return (Proc) proc;
67 }
Stephen White883c7e92019-10-17 10:44:37 -040068 if ((proc = wglGetProcAddress(name))) {
Stephen White985741a2019-07-18 11:43:45 -040069 return (Proc) proc;
70 }
71 return nullptr;
72 }
73
74 HMODULE fModule;
75 static ProcGetter* fInstance;
76};
77
78ProcGetter* ProcGetter::fInstance;
79#endif
80
81class DawnFence {
82public:
Stephen White3cc8d4f2019-10-30 09:56:23 -040083 DawnFence(const wgpu::Device& device, const wgpu::Buffer& buffer)
Stephen White985741a2019-07-18 11:43:45 -040084 : fDevice(device), fBuffer(buffer), fCalled(false) {
85 fBuffer.MapReadAsync(callback, this);
86 }
87
88 bool wait() {
89 while (!fCalled) {
90 fDevice.Tick();
91 }
92 return true;
93 }
94
95 ~DawnFence() {
96 }
97
Stephen Whitea521c962019-12-04 09:57:48 -050098 static void callback(WGPUBufferMapAsyncStatus status, const void* data, uint64_t dataLength,
Stephen White985741a2019-07-18 11:43:45 -040099 void* userData) {
100 DawnFence* fence = static_cast<DawnFence*>(userData);
101 fence->fCalled = true;
102 }
Stephen White3cc8d4f2019-10-30 09:56:23 -0400103 wgpu::Buffer buffer() { return fBuffer; }
Stephen White985741a2019-07-18 11:43:45 -0400104
105private:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400106 wgpu::Device fDevice;
107 wgpu::Buffer fBuffer;
Stephen White985741a2019-07-18 11:43:45 -0400108 bool fCalled;
109};
110
111/**
112 * Implements sk_gpu_test::FenceSync for Dawn.
113 */
114class DawnFenceSync : public sk_gpu_test::FenceSync {
115public:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400116 DawnFenceSync(wgpu::Device device) : fDevice(device) {
Stephen White985741a2019-07-18 11:43:45 -0400117 }
118
119 ~DawnFenceSync() override {
120 }
121
122 sk_gpu_test::PlatformFence SK_WARN_UNUSED_RESULT insertFence() const override {
Stephen White3cc8d4f2019-10-30 09:56:23 -0400123 wgpu::Buffer buffer;
Stephen White985741a2019-07-18 11:43:45 -0400124 if (fBuffers.empty()) {
Stephen White3cc8d4f2019-10-30 09:56:23 -0400125 wgpu::BufferDescriptor desc;
126 desc.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
Stephen White985741a2019-07-18 11:43:45 -0400127 desc.size = 1;
128 buffer = fDevice.CreateBuffer(&desc);
129 } else {
130 buffer = fBuffers.back();
131 fBuffers.pop_back();
132 }
133 DawnFence* fence = new DawnFence(fDevice, buffer);
134 return reinterpret_cast<sk_gpu_test::PlatformFence>(fence);
135 }
136
137 bool waitFence(sk_gpu_test::PlatformFence opaqueFence) const override {
138 fAutoreleasePool.drain();
139 DawnFence* fence = reinterpret_cast<DawnFence*>(opaqueFence);
140 return fence->wait();
141 }
142
143 void deleteFence(sk_gpu_test::PlatformFence opaqueFence) const override {
144 DawnFence* fence = reinterpret_cast<DawnFence*>(opaqueFence);
145 fBuffers.push_back(fence->buffer());
146 delete fence;
147 }
148
149private:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400150 wgpu::Device fDevice;
151 mutable std::vector<wgpu::Buffer> fBuffers;
Stephen White985741a2019-07-18 11:43:45 -0400152 mutable AutoreleasePool fAutoreleasePool;
153 typedef sk_gpu_test::FenceSync INHERITED;
154};
155
156class DawnTestContextImpl : public sk_gpu_test::DawnTestContext {
157public:
Stephen White3cc8d4f2019-10-30 09:56:23 -0400158 static wgpu::Device createDevice(const dawn_native::Instance& instance,
Stephen White985741a2019-07-18 11:43:45 -0400159 dawn_native::BackendType type) {
160 DawnProcTable backendProcs = dawn_native::GetProcs();
Stephen White1e2adcf2019-10-16 09:48:53 -0400161 dawnProcSetProcs(&backendProcs);
Stephen White985741a2019-07-18 11:43:45 -0400162
163 std::vector<dawn_native::Adapter> adapters = instance.GetAdapters();
164 for (dawn_native::Adapter adapter : adapters) {
165 if (adapter.GetBackendType() == type) {
166 return adapter.CreateDevice();
167 }
168 }
169 return nullptr;
170 }
171
172 static DawnTestContext* Create(DawnTestContext* sharedContext) {
173 std::unique_ptr<dawn_native::Instance> instance = std::make_unique<dawn_native::Instance>();
Stephen White3cc8d4f2019-10-30 09:56:23 -0400174 wgpu::Device device;
Stephen White985741a2019-07-18 11:43:45 -0400175 if (sharedContext) {
176 device = sharedContext->getDevice();
177 } else {
178 dawn_native::BackendType type;
179#if USE_OPENGL_BACKEND
180 dawn_native::opengl::AdapterDiscoveryOptions adapterOptions;
181 adapterOptions.getProc = reinterpret_cast<void*(*)(const char*)>(
182#if defined(SK_BUILD_FOR_UNIX)
183 glXGetProcAddress
184#elif defined(SK_BUILD_FOR_MAC)
185 getProcAddressMacOS
186#elif defined(SK_BUILD_FOR_WIN)
187 ProcGetter::getProcAddress
188#endif
189 );
190 instance->DiscoverAdapters(&adapterOptions);
191 type = dawn_native::BackendType::OpenGL;
192#else
193 instance->DiscoverDefaultAdapters();
194#if defined(SK_BUILD_FOR_MAC)
195 type = dawn_native::BackendType::Metal;
196#elif defined(SK_BUILD_FOR_WIN)
197 type = dawn_native::BackendType::D3D12;
198#elif defined(SK_BUILD_FOR_UNIX)
199 type = dawn_native::BackendType::Vulkan;
200#endif
201#endif
202 device = createDevice(*instance, type);
203 }
204 if (!device) {
205 return nullptr;
206 }
207 return new DawnTestContextImpl(std::move(instance), device);
208 }
209
210 ~DawnTestContextImpl() override { this->teardown(); }
211
212 void testAbandon() override {}
213
214 // There is really nothing to here since we don't own any unqueued command buffers here.
215 void submit() override {}
216
217 void finish() override {}
218
219 sk_sp<GrContext> makeGrContext(const GrContextOptions& options) override {
220 return GrContext::MakeDawn(fDevice, options);
221 }
222
223protected:
224 void teardown() override {
225 INHERITED::teardown();
226 }
227
228private:
229 DawnTestContextImpl(std::unique_ptr<dawn_native::Instance> instance,
Stephen White3cc8d4f2019-10-30 09:56:23 -0400230 const wgpu::Device& device)
Stephen White985741a2019-07-18 11:43:45 -0400231 : DawnTestContext(device)
232 , fInstance(std::move(instance)) {
233 fFenceSync.reset(new DawnFenceSync(fDevice));
234 }
235
Robert Phillipsedf3f382020-02-13 12:59:19 -0500236 void onPlatformMakeNotCurrent() const override {}
Stephen White985741a2019-07-18 11:43:45 -0400237 void onPlatformMakeCurrent() const override {}
238 std::function<void()> onPlatformGetAutoContextRestore() const override { return nullptr; }
239 void onPlatformSwapBuffers() const override {}
240 std::unique_ptr<dawn_native::Instance> fInstance;
241
242 typedef sk_gpu_test::DawnTestContext INHERITED;
243};
244} // anonymous namespace
245
246namespace sk_gpu_test {
247DawnTestContext* CreatePlatformDawnTestContext(DawnTestContext* sharedContext) {
248 return DawnTestContextImpl::Create(sharedContext);
249}
250} // namespace sk_gpu_test
251
252#endif