You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

176 lines
4.7 KiB

/*
* 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 <windows.h>
#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 <dlfcn.h>
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<dawn_native::Adapter> 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<dawn_native::Instance> instance = std::make_unique<dawn_native::Instance>();
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<void*(*)(const char*)>(
#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<GrDirectContext> makeContext(const GrContextOptions& options) override {
return GrDirectContext::MakeDawn(fDevice, options);
}
protected:
void teardown() override {
INHERITED::teardown();
}
private:
DawnTestContextImpl(std::unique_ptr<dawn_native::Instance> instance,
const wgpu::Device& device)
: DawnTestContext(std::move(instance), device) {
fFenceSupport = true;
}
void onPlatformMakeNotCurrent() const override {}
void onPlatformMakeCurrent() const override {}
std::function<void()> 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