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