/* * Copyright 2019 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "dawn/webgpu_cpp.h" #include "tools/gpu/dawn/DawnTestContext.h" #ifdef SK_BUILD_FOR_UNIX #include "GL/glx.h" #endif #ifdef SK_BUILD_FOR_WIN #include #endif #define USE_OPENGL_BACKEND 0 #ifdef SK_DAWN #include "dawn/webgpu.h" #include "dawn/dawn_proc.h" #include "include/gpu/GrDirectContext.h" #include "tools/AutoreleasePool.h" #if USE_OPENGL_BACKEND #include "dawn_native/OpenGLBackend.h" #endif #if defined(SK_BUILD_FOR_MAC) && USE_OPENGL_BACKEND #include static void* getProcAddressMacOS(const char* procName) { return dlsym(RTLD_DEFAULT, procName); } #endif namespace { #ifdef SK_BUILD_FOR_WIN class ProcGetter { public: typedef void(*Proc)(); ProcGetter() : fModule(LoadLibraryA("opengl32.dll")) { SkASSERT(!fInstance); fInstance = this; } ~ProcGetter() { if (fModule) { FreeLibrary(fModule); } fInstance = nullptr; } static void* getProcAddress(const char* name) { return fInstance->getProc(name); } private: Proc getProc(const char* name) { PROC proc; if ((proc = GetProcAddress(fModule, name))) { return (Proc) proc; } if ((proc = wglGetProcAddress(name))) { return (Proc) proc; } return nullptr; } HMODULE fModule; static ProcGetter* fInstance; }; ProcGetter* ProcGetter::fInstance; #endif static void PrintDeviceError(WGPUErrorType, const char* message, void*) { SkDebugf("Device error: %s\n", message); } class DawnTestContextImpl : public sk_gpu_test::DawnTestContext { public: static wgpu::Device createDevice(const dawn_native::Instance& instance, dawn_native::BackendType type) { DawnProcTable backendProcs = dawn_native::GetProcs(); dawnProcSetProcs(&backendProcs); std::vector adapters = instance.GetAdapters(); for (dawn_native::Adapter adapter : adapters) { if (adapter.GetBackendType() == type) { return wgpu::Device::Acquire(adapter.CreateDevice()); } } return nullptr; } static DawnTestContext* Create(DawnTestContext* sharedContext) { std::unique_ptr instance = std::make_unique(); wgpu::Device device; if (sharedContext) { device = sharedContext->getDevice(); } else { dawn_native::BackendType type; #if USE_OPENGL_BACKEND dawn_native::opengl::AdapterDiscoveryOptions adapterOptions; adapterOptions.getProc = reinterpret_cast( #if defined(SK_BUILD_FOR_UNIX) glXGetProcAddress #elif defined(SK_BUILD_FOR_MAC) getProcAddressMacOS #elif defined(SK_BUILD_FOR_WIN) ProcGetter::getProcAddress #endif ); instance->DiscoverAdapters(&adapterOptions); type = dawn_native::BackendType::OpenGL; #else instance->DiscoverDefaultAdapters(); #if defined(SK_BUILD_FOR_MAC) type = dawn_native::BackendType::Metal; #elif defined(SK_BUILD_FOR_WIN) type = dawn_native::BackendType::D3D12; #elif defined(SK_BUILD_FOR_UNIX) type = dawn_native::BackendType::Vulkan; #endif #endif device = createDevice(*instance, type); device.SetUncapturedErrorCallback(PrintDeviceError, 0); } if (!device) { return nullptr; } return new DawnTestContextImpl(std::move(instance), device); } ~DawnTestContextImpl() override { this->teardown(); } void testAbandon() override {} void finish() override {} sk_sp makeContext(const GrContextOptions& options) override { return GrDirectContext::MakeDawn(fDevice, options); } protected: void teardown() override { INHERITED::teardown(); } private: DawnTestContextImpl(std::unique_ptr instance, const wgpu::Device& device) : DawnTestContext(std::move(instance), device) { fFenceSupport = true; } void onPlatformMakeNotCurrent() const override {} void onPlatformMakeCurrent() const override {} std::function onPlatformGetAutoContextRestore() const override { return nullptr; } using INHERITED = sk_gpu_test::DawnTestContext; }; } // anonymous namespace namespace sk_gpu_test { DawnTestContext* CreatePlatformDawnTestContext(DawnTestContext* sharedContext) { return DawnTestContextImpl::Create(sharedContext); } } // namespace sk_gpu_test #endif