skia2/tools/gpu/dawn/DawnTestContext.cpp
Stephen White 64c8b811b5 Dawn: fix memory corruption in DawnTestContext.
Move the dawn_native::Instance ownership from DawnTestContextImpl to
DawnTestContext (its parent class), which owns the wgpu::Device.

dawn_native::Instance must outlive any wgpu::Devices created from it.

Bug: skia: 10311
Change-Id: Iedc4ed94f03b61d5e43cd5c93eb68e24bc4474e1
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/293852
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Stephen White <senorblanco@chromium.org>
2020-06-03 18:40:49 +00:00

171 lines
4.5 KiB
C++

/*
* 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/GrContext.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
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);
}
if (!device) {
return nullptr;
}
return new DawnTestContextImpl(std::move(instance), device);
}
~DawnTestContextImpl() override { this->teardown(); }
void testAbandon() override {}
void finish() override {}
sk_sp<GrContext> makeGrContext(const GrContextOptions& options) override {
return GrContext::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; }
typedef sk_gpu_test::DawnTestContext INHERITED;
};
} // anonymous namespace
namespace sk_gpu_test {
DawnTestContext* CreatePlatformDawnTestContext(DawnTestContext* sharedContext) {
return DawnTestContextImpl::Create(sharedContext);
}
} // namespace sk_gpu_test
#endif