diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index a7d5709020..002a2154c8 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -26,6 +26,7 @@ list(APPEND COMMON_SOURCES ${COMMON_DIR}/Platform.h ${COMMON_DIR}/Serial.h ${COMMON_DIR}/SerialQueue.h + ${COMMON_DIR}/SwapChainUtils.h ) add_library(nxt_common STATIC ${COMMON_SOURCES}) diff --git a/src/common/SwapChainUtils.h b/src/common/SwapChainUtils.h new file mode 100644 index 0000000000..b0a0871cee --- /dev/null +++ b/src/common/SwapChainUtils.h @@ -0,0 +1,38 @@ +// Copyright 2017 The NXT 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. + +#ifndef COMMON_SWAPCHAINUTILS_H_ +#define COMMON_SWAPCHAINUTILS_H_ + +template +nxtSwapChainImplementation CreateSwapChainImplementation(T* swapChain) { + nxtSwapChainImplementation impl = {}; + impl.userData = swapChain; + impl.Init = [](void* userData, void* wsiContext) { + auto* ctx = reinterpret_cast(wsiContext); + reinterpret_cast(userData)->Init(ctx); + }; + impl.Destroy = [](void* userData) { delete reinterpret_cast(userData); }; + impl.Configure = [](void* userData, nxtTextureFormat format, nxtTextureUsageBit allowedUsage, + uint32_t width, uint32_t height) { + return reinterpret_cast(userData)->Configure(format, allowedUsage, width, height); + }; + impl.GetNextTexture = [](void* userData, nxtSwapChainNextTexture* nextTexture) { + return reinterpret_cast(userData)->GetNextTexture(nextTexture); + }; + impl.Present = [](void* userData) { return reinterpret_cast(userData)->Present(); }; + return impl; +} + +#endif // COMMON_SWAPCHAINUTILS_H_ diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt index 8a96bbd907..26cbb0f186 100644 --- a/src/utils/CMakeLists.txt +++ b/src/utils/CMakeLists.txt @@ -19,7 +19,6 @@ list(APPEND UTILS_SOURCES ${UTILS_DIR}/BackendBinding.h ${UTILS_DIR}/NXTHelpers.cpp ${UTILS_DIR}/NXTHelpers.h - ${UTILS_DIR}/SwapChainImpl.h ${UTILS_DIR}/SystemUtils.cpp ${UTILS_DIR}/SystemUtils.h ) diff --git a/src/utils/D3D12Binding.cpp b/src/utils/D3D12Binding.cpp index 174ac25df3..9e55187545 100644 --- a/src/utils/D3D12Binding.cpp +++ b/src/utils/D3D12Binding.cpp @@ -15,8 +15,8 @@ #include "utils/BackendBinding.h" #include "common/Assert.h" +#include "common/SwapChainUtils.h" #include "nxt/nxt_wsi.h" -#include "utils/SwapChainImpl.h" #define GLFW_EXPOSE_NATIVE_WIN32 #include "GLFW/glfw3.h" @@ -116,32 +116,9 @@ namespace utils { } } // namespace - class SwapChainImplD3D12 : SwapChainImpl { + class SwapChainImplD3D12 { public: - static nxtSwapChainImplementation Create(HWND window, const nxtProcTable& procs) { - auto impl = GenerateSwapChainImplementation(); - impl.userData = new SwapChainImplD3D12(window, procs); - return impl; - } - - private: - nxtDevice mBackendDevice = nullptr; - nxtProcTable mProcs = {}; - - static constexpr unsigned int kFrameCount = 2; - - HWND mWindow = 0; - ComPtr mFactory = {}; - ComPtr mCommandQueue = {}; - ComPtr mSwapChain = {}; - ComPtr mRenderTargetResources[kFrameCount] = {}; - - // Frame synchronization. Updated every frame - uint32_t mRenderTargetIndex = 0; - uint32_t mPreviousRenderTargetIndex = 0; - uint64_t mLastSerialRenderTargetWasUsed[kFrameCount] = {}; - - D3D12_RESOURCE_STATES mRenderTargetResourceState; + using WSIContext = nxtWSIContextD3D12; SwapChainImplD3D12(HWND window, nxtProcTable procs) : mWindow(window), mProcs(procs), mFactory(CreateFactory()) { @@ -150,9 +127,6 @@ namespace utils { ~SwapChainImplD3D12() { } - // For GenerateSwapChainImplementation - friend class SwapChainImpl; - void Init(nxtWSIContextD3D12* ctx) { mBackendDevice = ctx->device; mCommandQueue = backend::d3d12::GetCommandQueue(mBackendDevice); @@ -249,6 +223,25 @@ namespace utils { return NXT_SWAP_CHAIN_NO_ERROR; } + + private: + nxtDevice mBackendDevice = nullptr; + nxtProcTable mProcs = {}; + + static constexpr unsigned int kFrameCount = 2; + + HWND mWindow = 0; + ComPtr mFactory = {}; + ComPtr mCommandQueue = {}; + ComPtr mSwapChain = {}; + ComPtr mRenderTargetResources[kFrameCount] = {}; + + // Frame synchronization. Updated every frame + uint32_t mRenderTargetIndex = 0; + uint32_t mPreviousRenderTargetIndex = 0; + uint64_t mLastSerialRenderTargetWasUsed[kFrameCount] = {}; + + D3D12_RESOURCE_STATES mRenderTargetResourceState; }; class D3D12Binding : public BackendBinding { @@ -271,7 +264,8 @@ namespace utils { uint64_t GetSwapChainImplementation() override { if (mSwapchainImpl.userData == nullptr) { HWND win32Window = glfwGetWin32Window(mWindow); - mSwapchainImpl = SwapChainImplD3D12::Create(win32Window, mProcTable); + mSwapchainImpl = + CreateSwapChainImplementation(new SwapChainImplD3D12(win32Window, mProcTable)); } return reinterpret_cast(&mSwapchainImpl); } diff --git a/src/utils/MetalBinding.mm b/src/utils/MetalBinding.mm index db8a78a93a..8f15b0e780 100644 --- a/src/utils/MetalBinding.mm +++ b/src/utils/MetalBinding.mm @@ -15,8 +15,8 @@ #include "utils/BackendBinding.h" #include "common/Assert.h" +#include "common/SwapChainUtils.h" #include "nxt/nxt_wsi.h" -#include "utils/SwapChainImpl.h" #define GLFW_EXPOSE_NATIVE_COCOA #include "GLFW/glfw3.h" @@ -32,22 +32,9 @@ namespace backend { namespace metal { }} namespace utils { - class SwapChainImplMTL : SwapChainImpl { + class SwapChainImplMTL { public: - static nxtSwapChainImplementation Create(id nswindow) { - auto impl = GenerateSwapChainImplementation(); - impl.userData = new SwapChainImplMTL(nswindow); - return impl; - } - - private: - id mNsWindow = nil; - id mMtlDevice = nil; - id mCommandQueue = nil; - - CAMetalLayer* mLayer = nullptr; - id mCurrentDrawable = nil; - id mCurrentTexture = nil; + using WSIContext = nxtWSIContextMetal; SwapChainImplMTL(id nsWindow) : mNsWindow(nsWindow) { } @@ -57,9 +44,6 @@ namespace utils { [mCurrentDrawable release]; } - // For GenerateSwapChainImplementation - friend class SwapChainImpl; - void Init(nxtWSIContextMetal* ctx) { mMtlDevice = ctx->device; mCommandQueue = [mMtlDevice newCommandQueue]; @@ -114,6 +98,15 @@ namespace utils { return NXT_SWAP_CHAIN_NO_ERROR; } + + private: + id mNsWindow = nil; + id mMtlDevice = nil; + id mCommandQueue = nil; + + CAMetalLayer* mLayer = nullptr; + id mCurrentDrawable = nil; + id mCurrentTexture = nil; }; class MetalBinding : public BackendBinding { @@ -130,7 +123,8 @@ namespace utils { uint64_t GetSwapChainImplementation() override { if (mSwapchainImpl.userData == nullptr) { - mSwapchainImpl = SwapChainImplMTL::Create(glfwGetCocoaWindow(mWindow)); + mSwapchainImpl = CreateSwapChainImplementation( + new SwapChainImplMTL(glfwGetCocoaWindow(mWindow))); } return reinterpret_cast(&mSwapchainImpl); } diff --git a/src/utils/OpenGLBinding.cpp b/src/utils/OpenGLBinding.cpp index 53f6c3bf6f..fd09c6052d 100644 --- a/src/utils/OpenGLBinding.cpp +++ b/src/utils/OpenGLBinding.cpp @@ -16,8 +16,8 @@ #include "common/Assert.h" #include "common/Platform.h" +#include "common/SwapChainUtils.h" #include "nxt/nxt_wsi.h" -#include "utils/SwapChainImpl.h" // Glad needs to be included before GLFW otherwise it complain that GL.h was already included #include "glad/glad.h" @@ -30,20 +30,9 @@ namespace backend { namespace opengl { }} // namespace backend::opengl namespace utils { - class SwapChainImplGL : SwapChainImpl { + class SwapChainImplGL { public: - static nxtSwapChainImplementation Create(GLFWwindow* window) { - auto impl = GenerateSwapChainImplementation(); - impl.userData = new SwapChainImplGL(window); - return impl; - } - - private: - GLFWwindow* mWindow = nullptr; - uint32_t mWidth = 0; - uint32_t mHeight = 0; - GLuint mBackFBO = 0; - GLuint mBackTexture = 0; + using WSIContext = nxtWSIContextGL; SwapChainImplGL(GLFWwindow* window) : mWindow(window) { } @@ -53,9 +42,6 @@ namespace utils { glDeleteFramebuffers(1, &mBackFBO); } - // For GenerateSwapChainImplementation - friend class SwapChainImpl; - void Init(nxtWSIContextGL*) { glGenTextures(1, &mBackTexture); glBindTexture(GL_TEXTURE_2D, mBackTexture); @@ -101,6 +87,13 @@ namespace utils { return NXT_SWAP_CHAIN_NO_ERROR; } + + private: + GLFWwindow* mWindow = nullptr; + uint32_t mWidth = 0; + uint32_t mHeight = 0; + GLuint mBackFBO = 0; + GLuint mBackTexture = 0; }; class OpenGLBinding : public BackendBinding { @@ -128,7 +121,7 @@ namespace utils { uint64_t GetSwapChainImplementation() override { if (mSwapchainImpl.userData == nullptr) { - mSwapchainImpl = SwapChainImplGL::Create(mWindow); + mSwapchainImpl = CreateSwapChainImplementation(new SwapChainImplGL(mWindow)); } return reinterpret_cast(&mSwapchainImpl); } diff --git a/src/utils/SwapChainImpl.h b/src/utils/SwapChainImpl.h deleted file mode 100644 index e09d74bf8c..0000000000 --- a/src/utils/SwapChainImpl.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2017 The NXT 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. - -#ifndef UTILS_SWAPCHAINIMPL_H_ -#define UTILS_SWAPCHAINIMPL_H_ - -namespace utils { - class SwapChainImpl { - protected: - template - static nxtSwapChainImplementation GenerateSwapChainImplementation() { - nxtSwapChainImplementation impl = {}; - impl.Init = [](void* userData, void* wsiContext) { - auto* ctx = reinterpret_cast(wsiContext); - reinterpret_cast(userData)->Init(ctx); - }; - impl.Destroy = [](void* userData) { delete reinterpret_cast(userData); }; - impl.Configure = [](void* userData, nxtTextureFormat format, - nxtTextureUsageBit allowedUsage, uint32_t width, uint32_t height) { - return reinterpret_cast(userData)->Configure(format, allowedUsage, width, - height); - }; - impl.GetNextTexture = [](void* userData, nxtSwapChainNextTexture* nextTexture) { - return reinterpret_cast(userData)->GetNextTexture(nextTexture); - }; - impl.Present = [](void* userData) { - return reinterpret_cast(userData)->Present(); - }; - return impl; - } - }; -} // namespace utils - -#endif // UTILS_SWAPCHAINIMPL_H_ diff --git a/src/utils/VulkanBinding.cpp b/src/utils/VulkanBinding.cpp index f5b982bf9b..e5f7188d7e 100644 --- a/src/utils/VulkanBinding.cpp +++ b/src/utils/VulkanBinding.cpp @@ -14,8 +14,8 @@ #include "utils/BackendBinding.h" +#include "common/SwapChainUtils.h" #include "nxt/nxt_wsi.h" -#include "utils/SwapChainImpl.h" namespace backend { namespace vulkan { void Init(nxtProcTable* procs, nxtDevice* device); @@ -23,24 +23,16 @@ namespace backend { namespace vulkan { namespace utils { - class SwapChainImplVulkan : SwapChainImpl { + class SwapChainImplVulkan { public: - static nxtSwapChainImplementation Create(GLFWwindow* window) { - auto impl = GenerateSwapChainImplementation(); - impl.userData = new SwapChainImplVulkan(window); - return impl; - } + using WSIContext = nxtWSIContextVulkan; - private: SwapChainImplVulkan(GLFWwindow* /*window*/) { } ~SwapChainImplVulkan() { } - // For GenerateSwapChainImplementation - friend class SwapChainImpl; - void Init(nxtWSIContextVulkan*) { } @@ -66,7 +58,7 @@ namespace utils { } uint64_t GetSwapChainImplementation() override { if (mSwapchainImpl.userData == nullptr) { - mSwapchainImpl = SwapChainImplVulkan::Create(mWindow); + mSwapchainImpl = CreateSwapChainImplementation(new SwapChainImplVulkan(mWindow)); } return reinterpret_cast(&mSwapchainImpl); }