Make SwapChainImpl a function and move it to common/

For the Vulkan backend it will make sense to have the SwapChain be
implemented inside the backend as it will need to interact with a lot of
things there. It will need SwapChainImpl and cannot see utils/ so
SwapChainImpl has to be moved in common/

Also makes SwapChainImpl a function called CreateSwapChainImplementation
as the inheritance was only used to share a static method.
This commit is contained in:
Corentin Wallez 2018-01-15 15:44:38 -05:00 committed by Corentin Wallez
parent 395bf15599
commit cc407ae787
8 changed files with 92 additions and 126 deletions

View File

@ -26,6 +26,7 @@ list(APPEND COMMON_SOURCES
${COMMON_DIR}/Platform.h ${COMMON_DIR}/Platform.h
${COMMON_DIR}/Serial.h ${COMMON_DIR}/Serial.h
${COMMON_DIR}/SerialQueue.h ${COMMON_DIR}/SerialQueue.h
${COMMON_DIR}/SwapChainUtils.h
) )
add_library(nxt_common STATIC ${COMMON_SOURCES}) add_library(nxt_common STATIC ${COMMON_SOURCES})

View File

@ -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 <typename T>
nxtSwapChainImplementation CreateSwapChainImplementation(T* swapChain) {
nxtSwapChainImplementation impl = {};
impl.userData = swapChain;
impl.Init = [](void* userData, void* wsiContext) {
auto* ctx = reinterpret_cast<typename T::WSIContext*>(wsiContext);
reinterpret_cast<T*>(userData)->Init(ctx);
};
impl.Destroy = [](void* userData) { delete reinterpret_cast<T*>(userData); };
impl.Configure = [](void* userData, nxtTextureFormat format, nxtTextureUsageBit allowedUsage,
uint32_t width, uint32_t height) {
return reinterpret_cast<T*>(userData)->Configure(format, allowedUsage, width, height);
};
impl.GetNextTexture = [](void* userData, nxtSwapChainNextTexture* nextTexture) {
return reinterpret_cast<T*>(userData)->GetNextTexture(nextTexture);
};
impl.Present = [](void* userData) { return reinterpret_cast<T*>(userData)->Present(); };
return impl;
}
#endif // COMMON_SWAPCHAINUTILS_H_

View File

@ -19,7 +19,6 @@ list(APPEND UTILS_SOURCES
${UTILS_DIR}/BackendBinding.h ${UTILS_DIR}/BackendBinding.h
${UTILS_DIR}/NXTHelpers.cpp ${UTILS_DIR}/NXTHelpers.cpp
${UTILS_DIR}/NXTHelpers.h ${UTILS_DIR}/NXTHelpers.h
${UTILS_DIR}/SwapChainImpl.h
${UTILS_DIR}/SystemUtils.cpp ${UTILS_DIR}/SystemUtils.cpp
${UTILS_DIR}/SystemUtils.h ${UTILS_DIR}/SystemUtils.h
) )

View File

@ -15,8 +15,8 @@
#include "utils/BackendBinding.h" #include "utils/BackendBinding.h"
#include "common/Assert.h" #include "common/Assert.h"
#include "common/SwapChainUtils.h"
#include "nxt/nxt_wsi.h" #include "nxt/nxt_wsi.h"
#include "utils/SwapChainImpl.h"
#define GLFW_EXPOSE_NATIVE_WIN32 #define GLFW_EXPOSE_NATIVE_WIN32
#include "GLFW/glfw3.h" #include "GLFW/glfw3.h"
@ -116,32 +116,9 @@ namespace utils {
} }
} // namespace } // namespace
class SwapChainImplD3D12 : SwapChainImpl { class SwapChainImplD3D12 {
public: public:
static nxtSwapChainImplementation Create(HWND window, const nxtProcTable& procs) { using WSIContext = nxtWSIContextD3D12;
auto impl = GenerateSwapChainImplementation<SwapChainImplD3D12, nxtWSIContextD3D12>();
impl.userData = new SwapChainImplD3D12(window, procs);
return impl;
}
private:
nxtDevice mBackendDevice = nullptr;
nxtProcTable mProcs = {};
static constexpr unsigned int kFrameCount = 2;
HWND mWindow = 0;
ComPtr<IDXGIFactory4> mFactory = {};
ComPtr<ID3D12CommandQueue> mCommandQueue = {};
ComPtr<IDXGISwapChain3> mSwapChain = {};
ComPtr<ID3D12Resource> mRenderTargetResources[kFrameCount] = {};
// Frame synchronization. Updated every frame
uint32_t mRenderTargetIndex = 0;
uint32_t mPreviousRenderTargetIndex = 0;
uint64_t mLastSerialRenderTargetWasUsed[kFrameCount] = {};
D3D12_RESOURCE_STATES mRenderTargetResourceState;
SwapChainImplD3D12(HWND window, nxtProcTable procs) SwapChainImplD3D12(HWND window, nxtProcTable procs)
: mWindow(window), mProcs(procs), mFactory(CreateFactory()) { : mWindow(window), mProcs(procs), mFactory(CreateFactory()) {
@ -150,9 +127,6 @@ namespace utils {
~SwapChainImplD3D12() { ~SwapChainImplD3D12() {
} }
// For GenerateSwapChainImplementation
friend class SwapChainImpl;
void Init(nxtWSIContextD3D12* ctx) { void Init(nxtWSIContextD3D12* ctx) {
mBackendDevice = ctx->device; mBackendDevice = ctx->device;
mCommandQueue = backend::d3d12::GetCommandQueue(mBackendDevice); mCommandQueue = backend::d3d12::GetCommandQueue(mBackendDevice);
@ -249,6 +223,25 @@ namespace utils {
return NXT_SWAP_CHAIN_NO_ERROR; return NXT_SWAP_CHAIN_NO_ERROR;
} }
private:
nxtDevice mBackendDevice = nullptr;
nxtProcTable mProcs = {};
static constexpr unsigned int kFrameCount = 2;
HWND mWindow = 0;
ComPtr<IDXGIFactory4> mFactory = {};
ComPtr<ID3D12CommandQueue> mCommandQueue = {};
ComPtr<IDXGISwapChain3> mSwapChain = {};
ComPtr<ID3D12Resource> 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 { class D3D12Binding : public BackendBinding {
@ -271,7 +264,8 @@ namespace utils {
uint64_t GetSwapChainImplementation() override { uint64_t GetSwapChainImplementation() override {
if (mSwapchainImpl.userData == nullptr) { if (mSwapchainImpl.userData == nullptr) {
HWND win32Window = glfwGetWin32Window(mWindow); HWND win32Window = glfwGetWin32Window(mWindow);
mSwapchainImpl = SwapChainImplD3D12::Create(win32Window, mProcTable); mSwapchainImpl =
CreateSwapChainImplementation(new SwapChainImplD3D12(win32Window, mProcTable));
} }
return reinterpret_cast<uint64_t>(&mSwapchainImpl); return reinterpret_cast<uint64_t>(&mSwapchainImpl);
} }

View File

@ -15,8 +15,8 @@
#include "utils/BackendBinding.h" #include "utils/BackendBinding.h"
#include "common/Assert.h" #include "common/Assert.h"
#include "common/SwapChainUtils.h"
#include "nxt/nxt_wsi.h" #include "nxt/nxt_wsi.h"
#include "utils/SwapChainImpl.h"
#define GLFW_EXPOSE_NATIVE_COCOA #define GLFW_EXPOSE_NATIVE_COCOA
#include "GLFW/glfw3.h" #include "GLFW/glfw3.h"
@ -32,22 +32,9 @@ namespace backend { namespace metal {
}} }}
namespace utils { namespace utils {
class SwapChainImplMTL : SwapChainImpl { class SwapChainImplMTL {
public: public:
static nxtSwapChainImplementation Create(id nswindow) { using WSIContext = nxtWSIContextMetal;
auto impl = GenerateSwapChainImplementation<SwapChainImplMTL, nxtWSIContextMetal>();
impl.userData = new SwapChainImplMTL(nswindow);
return impl;
}
private:
id mNsWindow = nil;
id<MTLDevice> mMtlDevice = nil;
id<MTLCommandQueue> mCommandQueue = nil;
CAMetalLayer* mLayer = nullptr;
id<CAMetalDrawable> mCurrentDrawable = nil;
id<MTLTexture> mCurrentTexture = nil;
SwapChainImplMTL(id nsWindow) : mNsWindow(nsWindow) { SwapChainImplMTL(id nsWindow) : mNsWindow(nsWindow) {
} }
@ -57,9 +44,6 @@ namespace utils {
[mCurrentDrawable release]; [mCurrentDrawable release];
} }
// For GenerateSwapChainImplementation
friend class SwapChainImpl;
void Init(nxtWSIContextMetal* ctx) { void Init(nxtWSIContextMetal* ctx) {
mMtlDevice = ctx->device; mMtlDevice = ctx->device;
mCommandQueue = [mMtlDevice newCommandQueue]; mCommandQueue = [mMtlDevice newCommandQueue];
@ -114,6 +98,15 @@ namespace utils {
return NXT_SWAP_CHAIN_NO_ERROR; return NXT_SWAP_CHAIN_NO_ERROR;
} }
private:
id mNsWindow = nil;
id<MTLDevice> mMtlDevice = nil;
id<MTLCommandQueue> mCommandQueue = nil;
CAMetalLayer* mLayer = nullptr;
id<CAMetalDrawable> mCurrentDrawable = nil;
id<MTLTexture> mCurrentTexture = nil;
}; };
class MetalBinding : public BackendBinding { class MetalBinding : public BackendBinding {
@ -130,7 +123,8 @@ namespace utils {
uint64_t GetSwapChainImplementation() override { uint64_t GetSwapChainImplementation() override {
if (mSwapchainImpl.userData == nullptr) { if (mSwapchainImpl.userData == nullptr) {
mSwapchainImpl = SwapChainImplMTL::Create(glfwGetCocoaWindow(mWindow)); mSwapchainImpl = CreateSwapChainImplementation(
new SwapChainImplMTL(glfwGetCocoaWindow(mWindow)));
} }
return reinterpret_cast<uint64_t>(&mSwapchainImpl); return reinterpret_cast<uint64_t>(&mSwapchainImpl);
} }

View File

@ -16,8 +16,8 @@
#include "common/Assert.h" #include "common/Assert.h"
#include "common/Platform.h" #include "common/Platform.h"
#include "common/SwapChainUtils.h"
#include "nxt/nxt_wsi.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 // Glad needs to be included before GLFW otherwise it complain that GL.h was already included
#include "glad/glad.h" #include "glad/glad.h"
@ -30,20 +30,9 @@ namespace backend { namespace opengl {
}} // namespace backend::opengl }} // namespace backend::opengl
namespace utils { namespace utils {
class SwapChainImplGL : SwapChainImpl { class SwapChainImplGL {
public: public:
static nxtSwapChainImplementation Create(GLFWwindow* window) { using WSIContext = nxtWSIContextGL;
auto impl = GenerateSwapChainImplementation<SwapChainImplGL, nxtWSIContextGL>();
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;
SwapChainImplGL(GLFWwindow* window) : mWindow(window) { SwapChainImplGL(GLFWwindow* window) : mWindow(window) {
} }
@ -53,9 +42,6 @@ namespace utils {
glDeleteFramebuffers(1, &mBackFBO); glDeleteFramebuffers(1, &mBackFBO);
} }
// For GenerateSwapChainImplementation
friend class SwapChainImpl;
void Init(nxtWSIContextGL*) { void Init(nxtWSIContextGL*) {
glGenTextures(1, &mBackTexture); glGenTextures(1, &mBackTexture);
glBindTexture(GL_TEXTURE_2D, mBackTexture); glBindTexture(GL_TEXTURE_2D, mBackTexture);
@ -101,6 +87,13 @@ namespace utils {
return NXT_SWAP_CHAIN_NO_ERROR; 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 { class OpenGLBinding : public BackendBinding {
@ -128,7 +121,7 @@ namespace utils {
uint64_t GetSwapChainImplementation() override { uint64_t GetSwapChainImplementation() override {
if (mSwapchainImpl.userData == nullptr) { if (mSwapchainImpl.userData == nullptr) {
mSwapchainImpl = SwapChainImplGL::Create(mWindow); mSwapchainImpl = CreateSwapChainImplementation(new SwapChainImplGL(mWindow));
} }
return reinterpret_cast<uint64_t>(&mSwapchainImpl); return reinterpret_cast<uint64_t>(&mSwapchainImpl);
} }

View File

@ -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 <class TImpl, typename TWSIContext>
static nxtSwapChainImplementation GenerateSwapChainImplementation() {
nxtSwapChainImplementation impl = {};
impl.Init = [](void* userData, void* wsiContext) {
auto* ctx = reinterpret_cast<TWSIContext*>(wsiContext);
reinterpret_cast<TImpl*>(userData)->Init(ctx);
};
impl.Destroy = [](void* userData) { delete reinterpret_cast<TImpl*>(userData); };
impl.Configure = [](void* userData, nxtTextureFormat format,
nxtTextureUsageBit allowedUsage, uint32_t width, uint32_t height) {
return reinterpret_cast<TImpl*>(userData)->Configure(format, allowedUsage, width,
height);
};
impl.GetNextTexture = [](void* userData, nxtSwapChainNextTexture* nextTexture) {
return reinterpret_cast<TImpl*>(userData)->GetNextTexture(nextTexture);
};
impl.Present = [](void* userData) {
return reinterpret_cast<TImpl*>(userData)->Present();
};
return impl;
}
};
} // namespace utils
#endif // UTILS_SWAPCHAINIMPL_H_

View File

@ -14,8 +14,8 @@
#include "utils/BackendBinding.h" #include "utils/BackendBinding.h"
#include "common/SwapChainUtils.h"
#include "nxt/nxt_wsi.h" #include "nxt/nxt_wsi.h"
#include "utils/SwapChainImpl.h"
namespace backend { namespace vulkan { namespace backend { namespace vulkan {
void Init(nxtProcTable* procs, nxtDevice* device); void Init(nxtProcTable* procs, nxtDevice* device);
@ -23,24 +23,16 @@ namespace backend { namespace vulkan {
namespace utils { namespace utils {
class SwapChainImplVulkan : SwapChainImpl { class SwapChainImplVulkan {
public: public:
static nxtSwapChainImplementation Create(GLFWwindow* window) { using WSIContext = nxtWSIContextVulkan;
auto impl = GenerateSwapChainImplementation<SwapChainImplVulkan, nxtWSIContextVulkan>();
impl.userData = new SwapChainImplVulkan(window);
return impl;
}
private:
SwapChainImplVulkan(GLFWwindow* /*window*/) { SwapChainImplVulkan(GLFWwindow* /*window*/) {
} }
~SwapChainImplVulkan() { ~SwapChainImplVulkan() {
} }
// For GenerateSwapChainImplementation
friend class SwapChainImpl;
void Init(nxtWSIContextVulkan*) { void Init(nxtWSIContextVulkan*) {
} }
@ -66,7 +58,7 @@ namespace utils {
} }
uint64_t GetSwapChainImplementation() override { uint64_t GetSwapChainImplementation() override {
if (mSwapchainImpl.userData == nullptr) { if (mSwapchainImpl.userData == nullptr) {
mSwapchainImpl = SwapChainImplVulkan::Create(mWindow); mSwapchainImpl = CreateSwapChainImplementation(new SwapChainImplVulkan(mWindow));
} }
return reinterpret_cast<uint64_t>(&mSwapchainImpl); return reinterpret_cast<uint64_t>(&mSwapchainImpl);
} }