From 90e594ee8bd6900d8d28abb159e9dfc2b7d7b3a4 Mon Sep 17 00:00:00 2001 From: Corentin Wallez Date: Mon, 7 Jan 2019 09:48:03 +0000 Subject: [PATCH] OpenGL: Implement the backend connection and adapter. The OpenGL backend can't gather discover default adapters because it needs getProc to do anything so we add DiscoverAdapters method to Instance that takes backend-specific options. dawn_native::opengl::CreateDevice is removed in favor of the adapter path so OpenGLBinding is modified to create an instance locally. This is only temporary until all backends support adapters, at which point a lot of *Binding code will be factored. Also contains a small fix for Result with movable types. BUG=dawn:29 Change-Id: I4eb3d4a14a871af73e1872132aff72b45e5fe566 Reviewed-on: https://dawn-review.googlesource.com/c/3663 Commit-Queue: Corentin Wallez Reviewed-by: Kai Ninomiya --- BUILD.gn | 2 + src/common/Result.h | 6 +- src/dawn_native/BackendConnection.cpp | 5 ++ src/dawn_native/BackendConnection.h | 4 ++ src/dawn_native/DawnNative.cpp | 9 +++ src/dawn_native/Instance.cpp | 33 +++++++++ src/dawn_native/Instance.h | 7 ++ src/dawn_native/null/NullBackend.cpp | 6 +- src/dawn_native/opengl/BackendGL.cpp | 90 +++++++++++++++++++++++++ src/dawn_native/opengl/BackendGL.h | 31 +++++++++ src/dawn_native/opengl/DeviceGL.cpp | 16 ----- src/include/dawn_native/DawnNative.h | 13 ++++ src/include/dawn_native/OpenGLBackend.h | 11 ++- src/utils/OpenGLBinding.cpp | 15 ++++- 14 files changed, 221 insertions(+), 27 deletions(-) create mode 100644 src/dawn_native/opengl/BackendGL.cpp create mode 100644 src/dawn_native/opengl/BackendGL.h diff --git a/BUILD.gn b/BUILD.gn index 2673ebe58d..8a100902ec 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -535,6 +535,8 @@ source_set("libdawn_native_sources") { if (dawn_enable_opengl) { deps += [ "third_party:glad" ] sources += [ + "src/dawn_native/opengl/BackendGL.cpp", + "src/dawn_native/opengl/BackendGL.h", "src/dawn_native/opengl/BufferGL.cpp", "src/dawn_native/opengl/BufferGL.h", "src/dawn_native/opengl/CommandBufferGL.cpp", diff --git a/src/common/Result.h b/src/common/Result.h index b5bf5e5782..b4824fe62f 100644 --- a/src/common/Result.h +++ b/src/common/Result.h @@ -282,11 +282,11 @@ E* Result::GetErrorFromPayload(intptr_t payload) { // Implementation of Result template -Result::Result(T&& success) : mType(Success), mSuccess(success) { +Result::Result(T&& success) : mType(Success), mSuccess(std::move(success)) { } template -Result::Result(E&& error) : mType(Error), mError(error) { +Result::Result(E&& error) : mType(Error), mError(std::move(error)) { } template @@ -296,7 +296,7 @@ Result::~Result() { template Result::Result(Result&& other) - : mType(other.mType), mError(std::move(other.mError)), mSuccess(other.mSuccess) { + : mType(other.mType), mError(std::move(other.mError)), mSuccess(std::move(other.mSuccess)) { other.mType = Acquired; } template diff --git a/src/dawn_native/BackendConnection.cpp b/src/dawn_native/BackendConnection.cpp index 93356ff6b8..5a9d4b169f 100644 --- a/src/dawn_native/BackendConnection.cpp +++ b/src/dawn_native/BackendConnection.cpp @@ -28,4 +28,9 @@ namespace dawn_native { return mInstance; } + ResultOrError>> BackendConnection::DiscoverAdapters( + const AdapterDiscoveryOptionsBase* options) { + return DAWN_VALIDATION_ERROR("DiscoverAdapters not implemented for this backend."); + } + } // namespace dawn_native diff --git a/src/dawn_native/BackendConnection.h b/src/dawn_native/BackendConnection.h index 51626c3e25..e0e56994ec 100644 --- a/src/dawn_native/BackendConnection.h +++ b/src/dawn_native/BackendConnection.h @@ -36,6 +36,10 @@ namespace dawn_native { // options (such as debug adapters, custom driver libraries, etc.) virtual std::vector> DiscoverDefaultAdapters() = 0; + // Returns new adapters created with the backend-specific options. + virtual ResultOrError>> DiscoverAdapters( + const AdapterDiscoveryOptionsBase* options); + private: InstanceBase* mInstance = nullptr; BackendType mType; diff --git a/src/dawn_native/DawnNative.cpp b/src/dawn_native/DawnNative.cpp index 6bd7bb876f..d10e8cb1f6 100644 --- a/src/dawn_native/DawnNative.cpp +++ b/src/dawn_native/DawnNative.cpp @@ -54,6 +54,11 @@ namespace dawn_native { return reinterpret_cast(mImpl->CreateDevice()); } + // AdapterDiscoverOptionsBase + + AdapterDiscoveryOptionsBase::AdapterDiscoveryOptionsBase(BackendType type) : backendType(type) { + } + // Instance Instance::Instance() : mImpl(new InstanceBase()) { @@ -68,6 +73,10 @@ namespace dawn_native { mImpl->DiscoverDefaultAdapters(); } + bool Instance::DiscoverAdapters(const AdapterDiscoveryOptionsBase* options) { + return mImpl->DiscoverAdapters(options); + } + std::vector Instance::GetAdapters() const { // Adapters are owned by mImpl so it is safe to return non RAII pointers to them std::vector adapters; diff --git a/src/dawn_native/Instance.cpp b/src/dawn_native/Instance.cpp index 595f442fe9..2f7566c951 100644 --- a/src/dawn_native/Instance.cpp +++ b/src/dawn_native/Instance.cpp @@ -67,6 +67,11 @@ namespace dawn_native { } } + // This is just a wrapper around the real logic that uses Error.h error handling. + bool InstanceBase::DiscoverAdapters(const AdapterDiscoveryOptionsBase* options) { + return !ConsumedError(DiscoverAdaptersInternal(options)); + } + const std::vector>& InstanceBase::GetAdapters() const { return mAdapters; } @@ -103,6 +108,34 @@ namespace dawn_native { mBackendsConnected = true; } + ResultOrError InstanceBase::FindBackend(BackendType type) { + for (std::unique_ptr& backend : mBackends) { + if (backend->GetType() == type) { + return backend.get(); + } + } + + return DAWN_VALIDATION_ERROR("Backend isn't present."); + } + + MaybeError InstanceBase::DiscoverAdaptersInternal(const AdapterDiscoveryOptionsBase* options) { + EnsureBackendConnections(); + + BackendConnection* backend; + DAWN_TRY_ASSIGN(backend, FindBackend(options->backendType)); + + std::vector> newAdapters; + DAWN_TRY_ASSIGN(newAdapters, backend->DiscoverAdapters(options)); + + for (std::unique_ptr& adapter : newAdapters) { + ASSERT(adapter->GetBackendType() == backend->GetType()); + ASSERT(adapter->GetInstance() == this); + mAdapters.push_back(std::move(adapter)); + } + + return {}; + } + bool InstanceBase::ConsumedError(MaybeError maybeError) { if (maybeError.IsError()) { ErrorData* error = maybeError.AcquireError(); diff --git a/src/dawn_native/Instance.h b/src/dawn_native/Instance.h index 7fc4128b8d..835d51dfdc 100644 --- a/src/dawn_native/Instance.h +++ b/src/dawn_native/Instance.h @@ -34,6 +34,7 @@ namespace dawn_native { InstanceBase& operator=(const InstanceBase& other) = delete; void DiscoverDefaultAdapters(); + bool DiscoverAdapters(const AdapterDiscoveryOptionsBase* options); const std::vector>& GetAdapters() const; @@ -41,7 +42,13 @@ namespace dawn_native { bool ConsumedError(MaybeError maybeError); private: + // Lazily creates connections to all backends that have been compiled. void EnsureBackendConnections(); + // Finds the BackendConnection for `type` or returns an error. + ResultOrError FindBackend(BackendType type); + + MaybeError DiscoverAdaptersInternal(const AdapterDiscoveryOptionsBase* options); + bool mBackendsConnected = false; std::vector> mBackends; diff --git a/src/dawn_native/null/NullBackend.cpp b/src/dawn_native/null/NullBackend.cpp index 01ca980121..196f8dec51 100644 --- a/src/dawn_native/null/NullBackend.cpp +++ b/src/dawn_native/null/NullBackend.cpp @@ -36,9 +36,9 @@ namespace dawn_native { namespace null { } }; - class NullBackend : public BackendConnection { + class Backend : public BackendConnection { public: - NullBackend(InstanceBase* instance) : BackendConnection(instance, BackendType::Null) { + Backend(InstanceBase* instance) : BackendConnection(instance, BackendType::Null) { } std::vector> DiscoverDefaultAdapters() override { @@ -55,7 +55,7 @@ namespace dawn_native { namespace null { } BackendConnection* Connect(InstanceBase* instance) { - return new NullBackend(instance); + return new Backend(instance); } // Device diff --git a/src/dawn_native/opengl/BackendGL.cpp b/src/dawn_native/opengl/BackendGL.cpp new file mode 100644 index 0000000000..c11e250c93 --- /dev/null +++ b/src/dawn_native/opengl/BackendGL.cpp @@ -0,0 +1,90 @@ +// Copyright 2019 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "dawn_native/opengl/BackendGL.h" + +#include "dawn_native/OpenGLBackend.h" +#include "dawn_native/opengl/DeviceGL.h" + +namespace dawn_native { namespace opengl { + + // Implementation of OpenGLBackend.h + + AdapterDiscoveryOptions::AdapterDiscoveryOptions() + : AdapterDiscoveryOptionsBase(BackendType::OpenGL) { + } + + // The OpenGL backend's Adapter. + + class Adapter : public AdapterBase { + public: + Adapter(InstanceBase* instance, const AdapterDiscoveryOptions* options) + : AdapterBase(instance, BackendType::OpenGL) { + // Use getProc to populate GLAD. + gladLoadGLLoader(reinterpret_cast(options->getProc)); + + // Set state that never changes between devices. + glEnable(GL_DEPTH_TEST); + glEnable(GL_SCISSOR_TEST); + glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX); + } + virtual ~Adapter() = default; + + private: + ResultOrError CreateDeviceImpl() override { + // There is no limit on the number of devices created from this adapter because they can + // all share the same backing OpenGL context. + return {new Device}; + } + }; + + // Implementation of the OpenGL backend's BackendConnection + + Backend::Backend(InstanceBase* instance) : BackendConnection(instance, BackendType::OpenGL) { + } + + std::vector> Backend::DiscoverDefaultAdapters() { + // The OpenGL backend needs at least "getProcAddress" to discover an adapter. + return {}; + } + + ResultOrError>> Backend::DiscoverAdapters( + const AdapterDiscoveryOptionsBase* optionsBase) { + // TODO(cwallez@chromium.org): For now we can only create a single adapter because glad uses + // static variables to store the pointers to OpenGL procs. Also, if we could create + // multiple adapters, we would need to figure out what to do about MakeCurrent. + if (mCreatedAdapter) { + return DAWN_VALIDATION_ERROR("The OpenGL backend can only create a single adapter"); + } + + ASSERT(optionsBase->backendType == BackendType::OpenGL); + const AdapterDiscoveryOptions* options = + reinterpret_cast(optionsBase); + + if (options->getProc == nullptr) { + return DAWN_VALIDATION_ERROR("AdapterDiscoveryOptions::getProc must be set"); + } + + std::vector> adapters; + adapters.push_back(std::make_unique(GetInstance(), options)); + + mCreatedAdapter = true; + return std::move(adapters); + } + + BackendConnection* Connect(InstanceBase* instance) { + return new Backend(instance); + } + +}} // namespace dawn_native::opengl diff --git a/src/dawn_native/opengl/BackendGL.h b/src/dawn_native/opengl/BackendGL.h new file mode 100644 index 0000000000..eb5923ab3c --- /dev/null +++ b/src/dawn_native/opengl/BackendGL.h @@ -0,0 +1,31 @@ +// Copyright 2019 The Dawn Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "dawn_native/BackendConnection.h" + +namespace dawn_native { namespace opengl { + + class Backend : public BackendConnection { + public: + Backend(InstanceBase* instance); + + std::vector> DiscoverDefaultAdapters() override; + ResultOrError>> DiscoverAdapters( + const AdapterDiscoveryOptionsBase* options) override; + + private: + bool mCreatedAdapter = false; + }; + +}} // namespace dawn_native::opengl diff --git a/src/dawn_native/opengl/DeviceGL.cpp b/src/dawn_native/opengl/DeviceGL.cpp index 833f7e23f4..4ffb1bbeb4 100644 --- a/src/dawn_native/opengl/DeviceGL.cpp +++ b/src/dawn_native/opengl/DeviceGL.cpp @@ -33,22 +33,6 @@ namespace dawn_native { namespace opengl { - dawnDevice CreateDevice(void* (*getProc)(const char*)) { - gladLoadGLLoader(reinterpret_cast(getProc)); - - glEnable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX); - - return reinterpret_cast(new Device); - } - - BackendConnection* Connect(InstanceBase* instance) { - return nullptr; - } - - // Device - Device::Device() { CollectPCIInfo(); } diff --git a/src/include/dawn_native/DawnNative.h b/src/include/dawn_native/DawnNative.h index 842e554d56..c1c439edf1 100644 --- a/src/include/dawn_native/DawnNative.h +++ b/src/include/dawn_native/DawnNative.h @@ -64,6 +64,15 @@ namespace dawn_native { AdapterBase* mImpl = nullptr; }; + // Base class for options passed to Instance::DiscoverAdapters. + struct DAWN_NATIVE_EXPORT AdapterDiscoveryOptionsBase { + public: + const BackendType backendType; + + protected: + AdapterDiscoveryOptionsBase(BackendType type); + }; + // Represents a connection to dawn_native and is used for dependency injection, discovering // system adapters and injecting custom adapters (like a Swiftshader Vulkan adapter). // @@ -81,6 +90,10 @@ namespace dawn_native { // adapters will later be returned by GetAdapters. void DiscoverDefaultAdapters(); + // Adds adapters that can be discovered with the options provided (like a getProcAddress). + // The backend is chosen based on the type of the options used. Returns true on success. + bool DiscoverAdapters(const AdapterDiscoveryOptionsBase* options); + // Returns all the adapters that the instance knows about. std::vector GetAdapters() const; diff --git a/src/include/dawn_native/OpenGLBackend.h b/src/include/dawn_native/OpenGLBackend.h index e31f7d38d5..10b00004a5 100644 --- a/src/include/dawn_native/OpenGLBackend.h +++ b/src/include/dawn_native/OpenGLBackend.h @@ -15,11 +15,16 @@ #ifndef DAWNNATIVE_OPENGLBACKEND_H_ #define DAWNNATIVE_OPENGLBACKEND_H_ -#include -#include +#include namespace dawn_native { namespace opengl { - DAWN_NATIVE_EXPORT dawnDevice CreateDevice(void* (*getProc)(const char*)); + + struct DAWN_NATIVE_EXPORT AdapterDiscoveryOptions : public AdapterDiscoveryOptionsBase { + AdapterDiscoveryOptions(); + + void* (*getProc)(const char*); + }; + }} // namespace dawn_native::opengl #endif // DAWNNATIVE_OPENGLBACKEND_H_ diff --git a/src/utils/OpenGLBinding.cpp b/src/utils/OpenGLBinding.cpp index a0fbc002a6..146cfbee8e 100644 --- a/src/utils/OpenGLBinding.cpp +++ b/src/utils/OpenGLBinding.cpp @@ -108,13 +108,23 @@ namespace utils { glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #endif } + dawnDevice CreateDevice() override { glfwMakeContextCurrent(mWindow); // Load the GL entry points in our copy of the glad static library gladLoadGLLoader(reinterpret_cast(glfwGetProcAddress)); - return dawn_native::opengl::CreateDevice( - 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 { @@ -129,6 +139,7 @@ namespace utils { } private: + std::unique_ptr mInstance; dawnSwapChainImplementation mSwapchainImpl = {}; };