Simplify BackendBinding following adapters.

It doesn't need to care about device creation anymore, except for the
GLFW window hints and creating a GL context to discover the adapter.

Also remove the non-adapter GetPCIInfo.

BUG=dawn:29

Change-Id: I9bc8232536a55d2f973463ae0f2e0548dfc35456
Reviewed-on: https://dawn-review.googlesource.com/c/4381
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
Corentin Wallez 2019-02-12 15:48:15 +00:00 committed by Commit Bot service account
parent 5987c4e839
commit bb5696bcd3
14 changed files with 139 additions and 170 deletions

View File

@ -27,6 +27,7 @@
#include <dawn_wire/WireServer.h>
#include "GLFW/glfw3.h"
#include <algorithm>
#include <cstring>
#include <iostream>
@ -59,6 +60,7 @@ enum class CmdBufType {
#endif
static CmdBufType cmdBufType = CmdBufType::Terrible;
static std::unique_ptr<dawn_native::Instance> instance;
static utils::BackendBinding* binding = nullptr;
static GLFWwindow* window = nullptr;
@ -69,29 +71,45 @@ static utils::TerribleCommandBuffer* c2sBuf = nullptr;
static utils::TerribleCommandBuffer* s2cBuf = nullptr;
dawn::Device CreateCppDawnDevice() {
binding = utils::CreateBinding(backendType);
if (binding == nullptr) {
return dawn::Device();
}
glfwSetErrorCallback(PrintGLFWError);
if (!glfwInit()) {
return dawn::Device();
}
binding->SetupGLFWWindowHints();
// Create the test window and discover adapters using it (esp. for OpenGL)
utils::SetupGLFWWindowHintsForBackend(backendType);
window = glfwCreateWindow(640, 480, "Dawn window", nullptr, nullptr);
if (!window) {
return dawn::Device();
}
binding->SetWindow(window);
instance = std::make_unique<dawn_native::Instance>();
utils::DiscoverAdapter(instance.get(), window, backendType);
dawnDevice backendDevice = binding->CreateDevice();
// Get an adapter for the backend to use, and create the device.
dawn_native::Adapter backendAdapter;
{
std::vector<dawn_native::Adapter> adapters = instance->GetAdapters();
auto adapterIt = std::find_if(adapters.begin(), adapters.end(),
[](const dawn_native::Adapter adapter) -> bool {
return adapter.GetBackendType() == backendType;
});
ASSERT(adapterIt != adapters.end());
backendAdapter = *adapterIt;
}
dawnDevice backendDevice = backendAdapter.CreateDevice();
dawnProcTable backendProcs = dawn_native::GetProcs();
binding = utils::CreateBinding(backendType, window, backendDevice);
if (binding == nullptr) {
return dawn::Device();
}
// Choose whether to use the backend procs and devices directly, or set up the wire.
dawnDevice cDevice = nullptr;
dawnProcTable procs;
switch (cmdBufType) {
case CmdBufType::None:
procs = backendProcs;

View File

@ -26,11 +26,6 @@ namespace dawn_native {
return GetProcsAutogen();
}
const PCIInfo& GetPCIInfo(dawnDevice device) {
DeviceBase* deviceBase = reinterpret_cast<DeviceBase*>(device);
return deviceBase->GetPCIInfo();
}
// Adapter
Adapter::Adapter() = default;
@ -50,6 +45,10 @@ namespace dawn_native {
return mImpl->GetPCIInfo();
}
Adapter::operator bool() const {
return mImpl != nullptr;
}
dawnDevice Adapter::CreateDevice() {
return reinterpret_cast<dawnDevice>(mImpl->CreateDevice());
}

View File

@ -102,11 +102,6 @@ namespace dawn_native {
mCaches->bindGroupLayouts.erase(obj);
}
const PCIInfo& DeviceBase::GetPCIInfo() const {
ASSERT(mAdapter != nullptr);
return mAdapter->GetPCIInfo();
}
// Object creation API methods
BindGroupBase* DeviceBase::CreateBindGroup(const BindGroupDescriptor* descriptor) {

View File

@ -114,8 +114,6 @@ namespace dawn_native {
return nullptr;
}
virtual const PCIInfo& GetPCIInfo() const;
virtual ResultOrError<std::unique_ptr<StagingBufferBase>> CreateStagingBuffer(
size_t size) = 0;
virtual MaybeError CopyFromStagingToBuffer(StagingBufferBase* source,

View File

@ -55,6 +55,8 @@ namespace dawn_native {
BackendType GetBackendType() const;
const PCIInfo& GetPCIInfo() const;
explicit operator bool() const;
// Create a device on this adapter, note that the interface will change to include at least
// a device descriptor and a pointer to backend specific options.
// On an error, nullptr is returned.
@ -104,8 +106,6 @@ namespace dawn_native {
// Backend-agnostic API for dawn_native
DAWN_NATIVE_EXPORT dawnProcTable GetProcs();
DAWN_NATIVE_EXPORT const PCIInfo& GetPCIInfo(dawnDevice device);
} // namespace dawn_native
#endif // DAWNNATIVE_DAWNNATIVE_H_

View File

@ -26,6 +26,7 @@
#include "utils/SystemUtils.h"
#include "utils/TerribleCommandBuffer.h"
#include <algorithm>
#include <iostream>
#include <unordered_map>
#include "GLFW/glfw3.h"
@ -55,7 +56,7 @@ namespace {
std::unordered_map<dawn_native::BackendType, GLFWwindow*> windows;
// Creates a GLFW window set up for use with a given backend.
GLFWwindow* GetWindowForBackend(utils::BackendBinding* binding, dawn_native::BackendType type) {
GLFWwindow* GetWindowForBackend(dawn_native::BackendType type) {
GLFWwindow** window = &windows[type];
if (*window != nullptr) {
@ -67,7 +68,7 @@ namespace {
}
glfwDefaultWindowHints();
binding->SetupGLFWWindowHints();
utils::SetupGLFWWindowHintsForBackend(type);
std::string windowName = "Dawn " + ParamName(type) + " test window";
*window = glfwCreateWindow(400, 400, windowName.c_str(), nullptr, nullptr);
@ -174,17 +175,35 @@ bool DawnTest::IsMacOS() const {
bool gTestUsesWire = false;
void DawnTest::SetUp() {
mBinding.reset(utils::CreateBinding(GetParam()));
DAWN_ASSERT(mBinding != nullptr);
GLFWwindow* testWindow = GetWindowForBackend(mBinding.get(), GetParam());
// Create the test window and discover adapters using it (esp. for OpenGL)
GLFWwindow* testWindow = GetWindowForBackend(GetParam());
DAWN_ASSERT(testWindow != nullptr);
mBinding->SetWindow(testWindow);
mInstance = std::make_unique<dawn_native::Instance>();
utils::DiscoverAdapter(mInstance.get(), testWindow, GetParam());
dawnDevice backendDevice = mBinding->CreateDevice();
// Get an adapter for the backend to use, and create the device.
dawn_native::Adapter backendAdapter;
{
std::vector<dawn_native::Adapter> adapters = mInstance->GetAdapters();
auto adapterIt = std::find_if(adapters.begin(), adapters.end(),
[this](const dawn_native::Adapter adapter) -> bool {
// Chromium's GTest harness has GetParam() as a regular
// function and not a member function of this.
DAWN_UNUSED(this);
return adapter.GetBackendType() == GetParam();
});
ASSERT(adapterIt != adapters.end());
backendAdapter = *adapterIt;
}
mPCIInfo = backendAdapter.GetPCIInfo();
dawnDevice backendDevice = backendAdapter.CreateDevice();
dawnProcTable backendProcs = dawn_native::GetProcs();
mBinding.reset(utils::CreateBinding(GetParam(), testWindow, backendDevice));
DAWN_ASSERT(mBinding != nullptr);
// Choose whether to use the backend procs and devices directly, or set up the wire.
dawnDevice cDevice = nullptr;
dawnProcTable procs;
@ -225,8 +244,6 @@ void DawnTest::SetUp() {
// The end2end tests should never cause validation errors. These should be tested in unittests.
device.SetErrorCallback(DeviceErrorCauseTestFailure, 0);
mPCIInfo = dawn_native::GetPCIInfo(backendDevice);
}
void DawnTest::TearDown() {

View File

@ -177,6 +177,7 @@ class DawnTest : public ::testing::TestWithParam<dawn_native::BackendType> {
// Assuming the data is mapped, checks all expectations
void ResolveExpectations();
std::unique_ptr<dawn_native::Instance> mInstance;
std::unique_ptr<utils::BackendBinding> mBinding;
dawn_native::PCIInfo mPCIInfo;

View File

@ -14,55 +14,92 @@
#include "utils/BackendBinding.h"
#include "common/Assert.h"
#include "common/Compiler.h"
#include "GLFW/glfw3.h"
#if defined(DAWN_ENABLE_BACKEND_OPENGL)
# include "dawn_native/OpenGLBackend.h"
#endif // defined(DAWN_ENABLE_BACKEND_OPENGL)
namespace utils {
#if defined(DAWN_ENABLE_BACKEND_D3D12)
BackendBinding* CreateD3D12Binding();
BackendBinding* CreateD3D12Binding(GLFWwindow* window, dawnDevice device);
#endif
#if defined(DAWN_ENABLE_BACKEND_METAL)
BackendBinding* CreateMetalBinding();
BackendBinding* CreateMetalBinding(GLFWwindow* window, dawnDevice device);
#endif
#if defined(DAWN_ENABLE_BACKEND_NULL)
BackendBinding* CreateNullBinding();
BackendBinding* CreateNullBinding(GLFWwindow* window, dawnDevice device);
#endif
#if defined(DAWN_ENABLE_BACKEND_OPENGL)
BackendBinding* CreateOpenGLBinding();
BackendBinding* CreateOpenGLBinding(GLFWwindow* window, dawnDevice device);
#endif
#if defined(DAWN_ENABLE_BACKEND_VULKAN)
BackendBinding* CreateVulkanBinding();
BackendBinding* CreateVulkanBinding(GLFWwindow* window, dawnDevice device);
#endif
void BackendBinding::SetWindow(GLFWwindow* window) {
mWindow = window;
BackendBinding::BackendBinding(GLFWwindow* window, dawnDevice device)
: mWindow(window), mDevice(device) {
}
BackendBinding* CreateBinding(dawn_native::BackendType type) {
void SetupGLFWWindowHintsForBackend(dawn_native::BackendType type) {
if (type == dawn_native::BackendType::OpenGL) {
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
} else {
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
}
}
void DiscoverAdapter(dawn_native::Instance* instance,
GLFWwindow* window,
dawn_native::BackendType type) {
DAWN_UNUSED(type);
DAWN_UNUSED(window);
if (type == dawn_native::BackendType::OpenGL) {
#if defined(DAWN_ENABLE_BACKEND_OPENGL)
glfwMakeContextCurrent(window);
dawn_native::opengl::AdapterDiscoveryOptions adapterOptions;
adapterOptions.getProc = reinterpret_cast<void* (*)(const char*)>(glfwGetProcAddress);
instance->DiscoverAdapters(&adapterOptions);
#endif // defined(DAWN_ENABLE_BACKEND_OPENGL)
} else {
instance->DiscoverDefaultAdapters();
}
}
BackendBinding* CreateBinding(dawn_native::BackendType type,
GLFWwindow* window,
dawnDevice device) {
switch (type) {
#if defined(DAWN_ENABLE_BACKEND_D3D12)
case dawn_native::BackendType::D3D12:
return CreateD3D12Binding();
return CreateD3D12Binding(window, device);
#endif
#if defined(DAWN_ENABLE_BACKEND_METAL)
case dawn_native::BackendType::Metal:
return CreateMetalBinding();
return CreateMetalBinding(window, device);
#endif
#if defined(DAWN_ENABLE_BACKEND_NULL)
case dawn_native::BackendType::Null:
return CreateNullBinding();
return CreateNullBinding(window, device);
#endif
#if defined(DAWN_ENABLE_BACKEND_OPENGL)
case dawn_native::BackendType::OpenGL:
return CreateOpenGLBinding();
return CreateOpenGLBinding(window, device);
#endif
#if defined(DAWN_ENABLE_BACKEND_VULKAN)
case dawn_native::BackendType::Vulkan:
return CreateVulkanBinding();
return CreateVulkanBinding(window, device);
#endif
default:

View File

@ -15,11 +15,10 @@
#ifndef UTILS_BACKENDBINDING_H_
#define UTILS_BACKENDBINDING_H_
#include <dawn_native/DawnNative.h>
#include "dawn/dawncpp.h"
#include "dawn_native/DawnNative.h"
struct GLFWwindow;
typedef struct dawnProcTable_s dawnProcTable;
typedef struct dawnDeviceImpl* dawnDevice;
namespace utils {
@ -27,18 +26,23 @@ namespace utils {
public:
virtual ~BackendBinding() = default;
virtual void SetupGLFWWindowHints() = 0;
virtual dawnDevice CreateDevice() = 0;
virtual uint64_t GetSwapChainImplementation() = 0;
virtual dawnTextureFormat GetPreferredSwapChainTextureFormat() = 0;
void SetWindow(GLFWwindow* window);
protected:
BackendBinding(GLFWwindow* window, dawnDevice device);
GLFWwindow* mWindow = nullptr;
dawnDevice mDevice = nullptr;
};
BackendBinding* CreateBinding(dawn_native::BackendType type);
void SetupGLFWWindowHintsForBackend(dawn_native::BackendType type);
void DiscoverAdapter(dawn_native::Instance* instance,
GLFWwindow* window,
dawn_native::BackendType type);
BackendBinding* CreateBinding(dawn_native::BackendType type,
GLFWwindow* window,
dawnDevice device);
} // namespace utils

View File

@ -27,30 +27,14 @@ namespace utils {
class D3D12Binding : public BackendBinding {
public:
void SetupGLFWWindowHints() override {
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
}
dawnDevice CreateDevice() override {
// Make an instance and find a D3D12 adapter
mInstance = std::make_unique<dawn_native::Instance>();
mInstance->DiscoverDefaultAdapters();
std::vector<dawn_native::Adapter> adapters = mInstance->GetAdapters();
for (dawn_native::Adapter adapter : adapters) {
if (adapter.GetBackendType() == dawn_native::BackendType::D3D12) {
mBackendDevice = adapter.CreateDevice();
return mBackendDevice;
}
}
UNREACHABLE();
D3D12Binding(GLFWwindow* window, dawnDevice device) : BackendBinding(window, device) {
}
uint64_t GetSwapChainImplementation() override {
if (mSwapchainImpl.userData == nullptr) {
HWND win32Window = glfwGetWin32Window(mWindow);
mSwapchainImpl =
dawn_native::d3d12::CreateNativeSwapChainImpl(mBackendDevice, win32Window);
dawn_native::d3d12::CreateNativeSwapChainImpl(mDevice, win32Window);
}
return reinterpret_cast<uint64_t>(&mSwapchainImpl);
}
@ -61,13 +45,11 @@ namespace utils {
}
private:
std::unique_ptr<dawn_native::Instance> mInstance;
dawnDevice mBackendDevice = nullptr;
dawnSwapChainImplementation mSwapchainImpl = {};
};
BackendBinding* CreateD3D12Binding() {
return new D3D12Binding;
BackendBinding* CreateD3D12Binding(GLFWwindow* window, dawnDevice device) {
return new D3D12Binding(window, device);
}
} // namespace utils

View File

@ -110,26 +110,7 @@ namespace utils {
class MetalBinding : public BackendBinding {
public:
void SetupGLFWWindowHints() override {
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
}
dawnDevice CreateDevice() override {
// Make an instance and find a Metal adapter
mInstance = std::make_unique<dawn_native::Instance>();
mInstance->DiscoverDefaultAdapters();
std::vector<dawn_native::Adapter> adapters = mInstance->GetAdapters();
for (dawn_native::Adapter adapter : adapters) {
if (adapter.GetBackendType() == dawn_native::BackendType::Metal) {
dawnDevice device = adapter.CreateDevice();
mMetalDevice = dawn_native::metal::GetMetalDevice(device);
return device;
}
}
UNREACHABLE();
return {};
MetalBinding(GLFWwindow* window, dawnDevice device) : BackendBinding(window, device) {
}
uint64_t GetSwapChainImplementation() override {
@ -145,12 +126,10 @@ namespace utils {
}
private:
std::unique_ptr<dawn_native::Instance> mInstance;
id<MTLDevice> mMetalDevice = nil;
dawnSwapChainImplementation mSwapchainImpl = {};
};
BackendBinding* CreateMetalBinding() {
return new MetalBinding;
BackendBinding* CreateMetalBinding(GLFWwindow* window, dawnDevice device) {
return new MetalBinding(window, device);
}
}

View File

@ -23,23 +23,9 @@ namespace utils {
class NullBinding : public BackendBinding {
public:
void SetupGLFWWindowHints() override {
NullBinding(GLFWwindow* window, dawnDevice device) : BackendBinding(window, device) {
}
dawnDevice CreateDevice() override {
// Make an instance and find the null adapter
mInstance = std::make_unique<dawn_native::Instance>();
mInstance->DiscoverDefaultAdapters();
std::vector<dawn_native::Adapter> adapters = mInstance->GetAdapters();
for (dawn_native::Adapter adapter : adapters) {
if (adapter.GetBackendType() == dawn_native::BackendType::Null) {
return adapter.CreateDevice();
}
}
UNREACHABLE();
return {};
}
uint64_t GetSwapChainImplementation() override {
if (mSwapchainImpl.userData == nullptr) {
mSwapchainImpl = dawn_native::null::CreateNativeSwapChainImpl();
@ -51,12 +37,11 @@ namespace utils {
}
private:
std::unique_ptr<dawn_native::Instance> mInstance;
dawnSwapChainImplementation mSwapchainImpl = {};
};
BackendBinding* CreateNullBinding() {
return new NullBinding;
BackendBinding* CreateNullBinding(GLFWwindow* window, dawnDevice device) {
return new NullBinding(window, device);
}
} // namespace utils

View File

@ -95,36 +95,9 @@ namespace utils {
class OpenGLBinding : public BackendBinding {
public:
void SetupGLFWWindowHints() override {
#if defined(DAWN_PLATFORM_APPLE)
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#else
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#endif
}
dawnDevice CreateDevice() override {
glfwMakeContextCurrent(mWindow);
OpenGLBinding(GLFWwindow* window, dawnDevice device) : BackendBinding(window, device) {
// Load the GL entry points in our copy of the glad static library
gladLoadGLLoader(reinterpret_cast<GLADloadproc>(glfwGetProcAddress));
// Make an instance and "discover" an OpenGL adapter with glfw's getProc
mInstance = std::make_unique<dawn_native::Instance>();
dawn_native::opengl::AdapterDiscoveryOptions adapterOptions;
adapterOptions.getProc = reinterpret_cast<void* (*)(const char*)>(glfwGetProcAddress);
mInstance->DiscoverAdapters(&adapterOptions);
std::vector<dawn_native::Adapter> adapters = mInstance->GetAdapters();
ASSERT(adapters.size() == 1);
return adapters[0].CreateDevice();
}
uint64_t GetSwapChainImplementation() override {
@ -139,12 +112,11 @@ namespace utils {
}
private:
std::unique_ptr<dawn_native::Instance> mInstance;
dawnSwapChainImplementation mSwapchainImpl = {};
};
BackendBinding* CreateOpenGLBinding() {
return new OpenGLBinding;
BackendBinding* CreateOpenGLBinding(GLFWwindow* window, dawnDevice device) {
return new OpenGLBinding(window, device);
}
} // namespace utils

View File

@ -26,25 +26,9 @@ namespace utils {
class VulkanBinding : public BackendBinding {
public:
void SetupGLFWWindowHints() override {
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
VulkanBinding(GLFWwindow* window, dawnDevice device) : BackendBinding(window, device) {
}
dawnDevice CreateDevice() override {
// Make an instance and find a Vulkan adapter
mInstance = std::make_unique<dawn_native::Instance>();
mInstance->DiscoverDefaultAdapters();
std::vector<dawn_native::Adapter> adapters = mInstance->GetAdapters();
for (dawn_native::Adapter adapter : adapters) {
if (adapter.GetBackendType() == dawn_native::BackendType::Vulkan) {
mDevice = adapter.CreateDevice();
return mDevice;
}
}
UNREACHABLE();
return {};
}
uint64_t GetSwapChainImplementation() override {
if (mSwapchainImpl.userData == nullptr) {
VkSurfaceKHR surface = VK_NULL_HANDLE;
@ -63,13 +47,11 @@ namespace utils {
}
private:
std::unique_ptr<dawn_native::Instance> mInstance;
dawnDevice mDevice = nullptr;
dawnSwapChainImplementation mSwapchainImpl = {};
};
BackendBinding* CreateVulkanBinding() {
return new VulkanBinding;
BackendBinding* CreateVulkanBinding(GLFWwindow* window, dawnDevice device) {
return new VulkanBinding(window, device);
}
} // namespace utils