diff --git a/examples/SampleUtils.cpp b/examples/SampleUtils.cpp index 7e1e7311f4..87f4982d73 100644 --- a/examples/SampleUtils.cpp +++ b/examples/SampleUtils.cpp @@ -27,6 +27,7 @@ #include #include "GLFW/glfw3.h" +#include #include #include @@ -59,6 +60,7 @@ enum class CmdBufType { #endif static CmdBufType cmdBufType = CmdBufType::Terrible; +static std::unique_ptr 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(); + 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 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; diff --git a/src/dawn_native/DawnNative.cpp b/src/dawn_native/DawnNative.cpp index d10e8cb1f6..5464d0d77e 100644 --- a/src/dawn_native/DawnNative.cpp +++ b/src/dawn_native/DawnNative.cpp @@ -26,11 +26,6 @@ namespace dawn_native { return GetProcsAutogen(); } - const PCIInfo& GetPCIInfo(dawnDevice device) { - DeviceBase* deviceBase = reinterpret_cast(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(mImpl->CreateDevice()); } diff --git a/src/dawn_native/Device.cpp b/src/dawn_native/Device.cpp index f0f879c0f9..8b33268278 100644 --- a/src/dawn_native/Device.cpp +++ b/src/dawn_native/Device.cpp @@ -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) { diff --git a/src/dawn_native/Device.h b/src/dawn_native/Device.h index 977ba73fb5..83c40c4e6a 100644 --- a/src/dawn_native/Device.h +++ b/src/dawn_native/Device.h @@ -114,8 +114,6 @@ namespace dawn_native { return nullptr; } - virtual const PCIInfo& GetPCIInfo() const; - virtual ResultOrError> CreateStagingBuffer( size_t size) = 0; virtual MaybeError CopyFromStagingToBuffer(StagingBufferBase* source, diff --git a/src/include/dawn_native/DawnNative.h b/src/include/dawn_native/DawnNative.h index c1c439edf1..e71e948abe 100644 --- a/src/include/dawn_native/DawnNative.h +++ b/src/include/dawn_native/DawnNative.h @@ -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_ diff --git a/src/tests/DawnTest.cpp b/src/tests/DawnTest.cpp index 357c0904a4..e82a3272a4 100644 --- a/src/tests/DawnTest.cpp +++ b/src/tests/DawnTest.cpp @@ -26,6 +26,7 @@ #include "utils/SystemUtils.h" #include "utils/TerribleCommandBuffer.h" +#include #include #include #include "GLFW/glfw3.h" @@ -55,7 +56,7 @@ namespace { std::unordered_map 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(); + 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 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() { diff --git a/src/tests/DawnTest.h b/src/tests/DawnTest.h index 7bce5ec46e..6dc6699bfb 100644 --- a/src/tests/DawnTest.h +++ b/src/tests/DawnTest.h @@ -177,6 +177,7 @@ class DawnTest : public ::testing::TestWithParam { // Assuming the data is mapped, checks all expectations void ResolveExpectations(); + std::unique_ptr mInstance; std::unique_ptr mBinding; dawn_native::PCIInfo mPCIInfo; diff --git a/src/utils/BackendBinding.cpp b/src/utils/BackendBinding.cpp index 3145856b0c..3e2b808372 100644 --- a/src/utils/BackendBinding.cpp +++ b/src/utils/BackendBinding.cpp @@ -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(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: diff --git a/src/utils/BackendBinding.h b/src/utils/BackendBinding.h index 44b7eb4f87..9cf31587aa 100644 --- a/src/utils/BackendBinding.h +++ b/src/utils/BackendBinding.h @@ -15,11 +15,10 @@ #ifndef UTILS_BACKENDBINDING_H_ #define UTILS_BACKENDBINDING_H_ -#include +#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 diff --git a/src/utils/D3D12Binding.cpp b/src/utils/D3D12Binding.cpp index e1c86875b1..8f6ec2807f 100644 --- a/src/utils/D3D12Binding.cpp +++ b/src/utils/D3D12Binding.cpp @@ -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(); - mInstance->DiscoverDefaultAdapters(); - - std::vector 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(&mSwapchainImpl); } @@ -61,13 +45,11 @@ namespace utils { } private: - std::unique_ptr mInstance; - dawnDevice mBackendDevice = nullptr; dawnSwapChainImplementation mSwapchainImpl = {}; }; - BackendBinding* CreateD3D12Binding() { - return new D3D12Binding; + BackendBinding* CreateD3D12Binding(GLFWwindow* window, dawnDevice device) { + return new D3D12Binding(window, device); } } // namespace utils diff --git a/src/utils/MetalBinding.mm b/src/utils/MetalBinding.mm index 51372533d6..bdc7d6ece9 100644 --- a/src/utils/MetalBinding.mm +++ b/src/utils/MetalBinding.mm @@ -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(); - mInstance->DiscoverDefaultAdapters(); - - std::vector 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 mInstance; - id mMetalDevice = nil; dawnSwapChainImplementation mSwapchainImpl = {}; }; - BackendBinding* CreateMetalBinding() { - return new MetalBinding; + BackendBinding* CreateMetalBinding(GLFWwindow* window, dawnDevice device) { + return new MetalBinding(window, device); } } diff --git a/src/utils/NullBinding.cpp b/src/utils/NullBinding.cpp index 213cca7f09..92c48b4784 100644 --- a/src/utils/NullBinding.cpp +++ b/src/utils/NullBinding.cpp @@ -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(); - mInstance->DiscoverDefaultAdapters(); - std::vector 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 mInstance; dawnSwapChainImplementation mSwapchainImpl = {}; }; - BackendBinding* CreateNullBinding() { - return new NullBinding; + BackendBinding* CreateNullBinding(GLFWwindow* window, dawnDevice device) { + return new NullBinding(window, device); } } // namespace utils diff --git a/src/utils/OpenGLBinding.cpp b/src/utils/OpenGLBinding.cpp index 146cfbee8e..08181015a3 100644 --- a/src/utils/OpenGLBinding.cpp +++ b/src/utils/OpenGLBinding.cpp @@ -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(glfwGetProcAddress)); - - // Make an instance and "discover" an OpenGL adapter with glfw's getProc - mInstance = std::make_unique(); - - dawn_native::opengl::AdapterDiscoveryOptions adapterOptions; - adapterOptions.getProc = reinterpret_cast(glfwGetProcAddress); - mInstance->DiscoverAdapters(&adapterOptions); - - std::vector 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 mInstance; dawnSwapChainImplementation mSwapchainImpl = {}; }; - BackendBinding* CreateOpenGLBinding() { - return new OpenGLBinding; + BackendBinding* CreateOpenGLBinding(GLFWwindow* window, dawnDevice device) { + return new OpenGLBinding(window, device); } } // namespace utils diff --git a/src/utils/VulkanBinding.cpp b/src/utils/VulkanBinding.cpp index c0714159dc..fe4d9436a0 100644 --- a/src/utils/VulkanBinding.cpp +++ b/src/utils/VulkanBinding.cpp @@ -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(); - mInstance->DiscoverDefaultAdapters(); - std::vector 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 mInstance; - dawnDevice mDevice = nullptr; dawnSwapChainImplementation mSwapchainImpl = {}; }; - BackendBinding* CreateVulkanBinding() { - return new VulkanBinding; + BackendBinding* CreateVulkanBinding(GLFWwindow* window, dawnDevice device) { + return new VulkanBinding(window, device); } } // namespace utils