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> 32static void* getProcAddressMacOS(const char* procName) { 33 return dlsym(RTLD_DEFAULT, procName); 34} 35#endif 36 37namespace { 38 39#ifdef SK_BUILD_FOR_WIN 40class ProcGetter { 41public: 42 typedef void(*Proc)(); 43 44 ProcGetter() 45 : fModule(LoadLibraryA("opengl32.dll")) { 46 SkASSERT(!fInstance); 47 fInstance = this; 48 } 49 50 ~ProcGetter() { 51 if (fModule) { 52 FreeLibrary(fModule); 53 } 54 fInstance = nullptr; 55 } 56 57 static void* getProcAddress(const char* name) { 58 return fInstance->getProc(name); 59 } 60 61private: 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 77ProcGetter* ProcGetter::fInstance; 78#endif 79 80static void PrintDeviceError(WGPUErrorType, const char* message, void*) { 81 SkDebugf("Device error: %s\n", message); 82} 83 84class DawnTestContextImpl : public sk_gpu_test::DawnTestContext { 85public: 86 static wgpu::Device createDevice(const dawn_native::Instance& instance, 87 dawn_native::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 if (adapter.GetBackendType() == type) { 94 return wgpu::Device::Acquire(adapter.CreateDevice()); 95 } 96 } 97 return nullptr; 98 } 99 100 static DawnTestContext* Create(DawnTestContext* sharedContext) { 101 std::unique_ptr<dawn_native::Instance> instance = std::make_unique<dawn_native::Instance>(); 102 wgpu::Device device; 103 if (sharedContext) { 104 device = sharedContext->getDevice(); 105 } else { 106 dawn_native::BackendType type; 107#if USE_OPENGL_BACKEND 108 dawn_native::opengl::AdapterDiscoveryOptions adapterOptions; 109 adapterOptions.getProc = reinterpret_cast<void*(*)(const char*)>( 110#if defined(SK_BUILD_FOR_UNIX) 111 glXGetProcAddress 112#elif defined(SK_BUILD_FOR_MAC) 113 getProcAddressMacOS 114#elif defined(SK_BUILD_FOR_WIN) 115 ProcGetter::getProcAddress 116#endif 117 ); 118 instance->DiscoverAdapters(&adapterOptions); 119 type = dawn_native::BackendType::OpenGL; 120#else 121 instance->DiscoverDefaultAdapters(); 122#if defined(SK_BUILD_FOR_MAC) 123 type = dawn_native::BackendType::Metal; 124#elif defined(SK_BUILD_FOR_WIN) 125 type = dawn_native::BackendType::D3D12; 126#elif defined(SK_BUILD_FOR_UNIX) 127 type = dawn_native::BackendType::Vulkan; 128#endif 129#endif 130 device = createDevice(*instance, type); 131 device.SetUncapturedErrorCallback(PrintDeviceError, 0); 132 } 133 if (!device) { 134 return nullptr; 135 } 136 return new DawnTestContextImpl(std::move(instance), device); 137 } 138 139 ~DawnTestContextImpl() override { this->teardown(); } 140 141 void testAbandon() override {} 142 143 void finish() override {} 144 145 sk_sp<GrDirectContext> makeContext(const GrContextOptions& options) override { 146 return GrDirectContext::MakeDawn(fDevice, options); 147 } 148 149protected: 150 void teardown() override { 151 INHERITED::teardown(); 152 } 153 154private: 155 DawnTestContextImpl(std::unique_ptr<dawn_native::Instance> instance, 156 const wgpu::Device& device) 157 : DawnTestContext(std::move(instance), device) { 158 fFenceSupport = true; 159 } 160 161 void onPlatformMakeNotCurrent() const override {} 162 void onPlatformMakeCurrent() const override {} 163 std::function<void()> onPlatformGetAutoContextRestore() const override { return nullptr; } 164 165 using INHERITED = sk_gpu_test::DawnTestContext; 166}; 167} // anonymous namespace 168 169namespace sk_gpu_test { 170DawnTestContext* CreatePlatformDawnTestContext(DawnTestContext* sharedContext) { 171 return DawnTestContextImpl::Create(sharedContext); 172} 173} // namespace sk_gpu_test 174 175#endif 176