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 = {}; };