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