mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-14 23:56:16 +00:00
Format: src/{common, utils, wire}
This commit is contained in:
committed by
Corentin Wallez
parent
a351ce9618
commit
9d01c6c26d
@@ -18,21 +18,21 @@
|
||||
|
||||
namespace utils {
|
||||
|
||||
#if defined(NXT_ENABLE_BACKEND_D3D12)
|
||||
BackendBinding* CreateD3D12Binding();
|
||||
#endif
|
||||
#if defined(NXT_ENABLE_BACKEND_METAL)
|
||||
BackendBinding* CreateMetalBinding();
|
||||
#endif
|
||||
#if defined(NXT_ENABLE_BACKEND_NULL)
|
||||
BackendBinding* CreateNullBinding();
|
||||
#endif
|
||||
#if defined(NXT_ENABLE_BACKEND_OPENGL)
|
||||
BackendBinding* CreateOpenGLBinding();
|
||||
#endif
|
||||
#if defined(NXT_ENABLE_BACKEND_VULKAN)
|
||||
BackendBinding* CreateVulkanBinding();
|
||||
#endif
|
||||
#if defined(NXT_ENABLE_BACKEND_D3D12)
|
||||
BackendBinding* CreateD3D12Binding();
|
||||
#endif
|
||||
#if defined(NXT_ENABLE_BACKEND_METAL)
|
||||
BackendBinding* CreateMetalBinding();
|
||||
#endif
|
||||
#if defined(NXT_ENABLE_BACKEND_NULL)
|
||||
BackendBinding* CreateNullBinding();
|
||||
#endif
|
||||
#if defined(NXT_ENABLE_BACKEND_OPENGL)
|
||||
BackendBinding* CreateOpenGLBinding();
|
||||
#endif
|
||||
#if defined(NXT_ENABLE_BACKEND_VULKAN)
|
||||
BackendBinding* CreateVulkanBinding();
|
||||
#endif
|
||||
|
||||
void BackendBinding::SetWindow(GLFWwindow* window) {
|
||||
mWindow = window;
|
||||
@@ -40,34 +40,34 @@ namespace utils {
|
||||
|
||||
BackendBinding* CreateBinding(BackendType type) {
|
||||
switch (type) {
|
||||
#if defined(NXT_ENABLE_BACKEND_D3D12)
|
||||
case BackendType::D3D12:
|
||||
return CreateD3D12Binding();
|
||||
#endif
|
||||
#if defined(NXT_ENABLE_BACKEND_D3D12)
|
||||
case BackendType::D3D12:
|
||||
return CreateD3D12Binding();
|
||||
#endif
|
||||
|
||||
#if defined(NXT_ENABLE_BACKEND_METAL)
|
||||
case BackendType::Metal:
|
||||
return CreateMetalBinding();
|
||||
#endif
|
||||
#if defined(NXT_ENABLE_BACKEND_METAL)
|
||||
case BackendType::Metal:
|
||||
return CreateMetalBinding();
|
||||
#endif
|
||||
|
||||
#if defined(NXT_ENABLE_BACKEND_NULL)
|
||||
case BackendType::Null:
|
||||
return CreateNullBinding();
|
||||
#endif
|
||||
#if defined(NXT_ENABLE_BACKEND_NULL)
|
||||
case BackendType::Null:
|
||||
return CreateNullBinding();
|
||||
#endif
|
||||
|
||||
#if defined(NXT_ENABLE_BACKEND_OPENGL)
|
||||
case BackendType::OpenGL:
|
||||
return CreateOpenGLBinding();
|
||||
#endif
|
||||
#if defined(NXT_ENABLE_BACKEND_OPENGL)
|
||||
case BackendType::OpenGL:
|
||||
return CreateOpenGLBinding();
|
||||
#endif
|
||||
|
||||
#if defined(NXT_ENABLE_BACKEND_VULKAN)
|
||||
case BackendType::Vulkan:
|
||||
return CreateVulkanBinding();
|
||||
#endif
|
||||
#if defined(NXT_ENABLE_BACKEND_VULKAN)
|
||||
case BackendType::Vulkan:
|
||||
return CreateVulkanBinding();
|
||||
#endif
|
||||
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace utils
|
||||
|
||||
@@ -32,21 +32,22 @@ namespace utils {
|
||||
};
|
||||
|
||||
class BackendBinding {
|
||||
public:
|
||||
virtual ~BackendBinding() = default;
|
||||
public:
|
||||
virtual ~BackendBinding() = default;
|
||||
|
||||
virtual void SetupGLFWWindowHints() = 0;
|
||||
virtual void GetProcAndDevice(nxtProcTable* procs, nxtDevice* device) = 0;
|
||||
virtual uint64_t GetSwapChainImplementation() = 0;
|
||||
virtual nxtTextureFormat GetPreferredSwapChainTextureFormat() = 0;
|
||||
virtual void SetupGLFWWindowHints() = 0;
|
||||
virtual void GetProcAndDevice(nxtProcTable* procs, nxtDevice* device) = 0;
|
||||
virtual uint64_t GetSwapChainImplementation() = 0;
|
||||
virtual nxtTextureFormat GetPreferredSwapChainTextureFormat() = 0;
|
||||
|
||||
void SetWindow(GLFWwindow* window);
|
||||
void SetWindow(GLFWwindow* window);
|
||||
|
||||
protected:
|
||||
GLFWwindow* mWindow = nullptr;
|
||||
protected:
|
||||
GLFWwindow* mWindow = nullptr;
|
||||
};
|
||||
|
||||
BackendBinding* CreateBinding(BackendType type);
|
||||
}
|
||||
|
||||
#endif // UTILS_BACKENDBINDING_H_
|
||||
} // namespace utils
|
||||
|
||||
#endif // UTILS_BACKENDBINDING_H_
|
||||
|
||||
@@ -22,27 +22,26 @@
|
||||
#include "GLFW/glfw3.h"
|
||||
#include "GLFW/glfw3native.h"
|
||||
|
||||
#include <initializer_list>
|
||||
#include <wrl.h>
|
||||
#include <d3d12.h>
|
||||
#include <dxgi1_4.h>
|
||||
#include <wrl.h>
|
||||
#include <initializer_list>
|
||||
#ifdef _DEBUG
|
||||
#include <dxgidebug.h>
|
||||
#endif
|
||||
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
namespace backend {
|
||||
namespace d3d12 {
|
||||
namespace backend { namespace d3d12 {
|
||||
void Init(ComPtr<ID3D12Device> d3d12Device, nxtProcTable* procs, nxtDevice* device);
|
||||
ComPtr<ID3D12CommandQueue> GetCommandQueue(nxtDevice device);
|
||||
uint64_t GetSerial(const nxtDevice device);
|
||||
void NextSerial(nxtDevice device);
|
||||
void ExecuteCommandLists(nxtDevice device, std::initializer_list<ID3D12CommandList*> commandLists);
|
||||
void ExecuteCommandLists(nxtDevice device,
|
||||
std::initializer_list<ID3D12CommandList*> commandLists);
|
||||
void WaitForSerial(nxtDevice device, uint64_t serial);
|
||||
void OpenCommandList(nxtDevice device, ComPtr<ID3D12GraphicsCommandList>* commandList);
|
||||
}
|
||||
}
|
||||
}} // namespace backend::d3d12
|
||||
|
||||
namespace utils {
|
||||
namespace {
|
||||
@@ -56,7 +55,8 @@ namespace utils {
|
||||
uint32_t dxgiFactoryFlags = 0;
|
||||
#ifdef _DEBUG
|
||||
// Enable the debug layer (requires the Graphics Tools "optional feature").
|
||||
// NOTE: Enabling the debug layer after device creation will invalidate the active device.
|
||||
// NOTE: Enabling the debug layer after device creation will invalidate the active
|
||||
// device.
|
||||
{
|
||||
ComPtr<ID3D12Debug> debugController;
|
||||
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) {
|
||||
@@ -68,7 +68,8 @@ namespace utils {
|
||||
|
||||
ComPtr<IDXGIDebug1> dxgiDebug;
|
||||
if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(&dxgiDebug)))) {
|
||||
dxgiDebug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_FLAGS(DXGI_DEBUG_RLO_ALL));
|
||||
dxgiDebug->ReportLiveObjects(DXGI_DEBUG_ALL,
|
||||
DXGI_DEBUG_RLO_FLAGS(DXGI_DEBUG_RLO_ALL));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -101,7 +102,8 @@ namespace utils {
|
||||
resourceState |= D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
}
|
||||
if (usage & NXT_TEXTURE_USAGE_BIT_SAMPLED) {
|
||||
resourceState |= (D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
|
||||
resourceState |= (D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE |
|
||||
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
|
||||
}
|
||||
if (usage & NXT_TEXTURE_USAGE_BIT_STORAGE) {
|
||||
resourceState |= D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
|
||||
@@ -112,204 +114,205 @@ namespace utils {
|
||||
|
||||
return resourceState;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class SwapChainImplD3D12 : SwapChainImpl {
|
||||
public:
|
||||
static nxtSwapChainImplementation Create(HWND window, const nxtProcTable& procs) {
|
||||
auto impl = GenerateSwapChainImplementation<SwapChainImplD3D12, nxtWSIContextD3D12>();
|
||||
impl.userData = new SwapChainImplD3D12(window, procs);
|
||||
return impl;
|
||||
public:
|
||||
static nxtSwapChainImplementation Create(HWND window, const nxtProcTable& procs) {
|
||||
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)
|
||||
: mWindow(window), mProcs(procs), mFactory(CreateFactory()) {
|
||||
}
|
||||
|
||||
~SwapChainImplD3D12() {
|
||||
}
|
||||
|
||||
// For GenerateSwapChainImplementation
|
||||
friend class SwapChainImpl;
|
||||
|
||||
void Init(nxtWSIContextD3D12* ctx) {
|
||||
mBackendDevice = ctx->device;
|
||||
mCommandQueue = backend::d3d12::GetCommandQueue(mBackendDevice);
|
||||
}
|
||||
|
||||
nxtSwapChainError Configure(nxtTextureFormat format,
|
||||
nxtTextureUsageBit allowedUsage,
|
||||
uint32_t width,
|
||||
uint32_t height) {
|
||||
if (format != NXT_TEXTURE_FORMAT_R8_G8_B8_A8_UNORM) {
|
||||
return "unsupported format";
|
||||
}
|
||||
ASSERT(width > 0);
|
||||
ASSERT(height > 0);
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
|
||||
swapChainDesc.Width = width;
|
||||
swapChainDesc.Height = height;
|
||||
swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
swapChainDesc.BufferUsage = D3D12SwapChainBufferUsage(allowedUsage);
|
||||
swapChainDesc.BufferCount = kFrameCount;
|
||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
swapChainDesc.SampleDesc.Count = 1;
|
||||
swapChainDesc.SampleDesc.Quality = 0;
|
||||
|
||||
ComPtr<IDXGISwapChain1> swapChain1;
|
||||
ASSERT_SUCCESS(mFactory->CreateSwapChainForHwnd(
|
||||
mCommandQueue.Get(), mWindow, &swapChainDesc, nullptr, nullptr, &swapChain1));
|
||||
ASSERT_SUCCESS(swapChain1.As(&mSwapChain));
|
||||
|
||||
for (uint32_t n = 0; n < kFrameCount; ++n) {
|
||||
ASSERT_SUCCESS(mSwapChain->GetBuffer(n, IID_PPV_ARGS(&mRenderTargetResources[n])));
|
||||
}
|
||||
|
||||
private:
|
||||
nxtDevice mBackendDevice = nullptr;
|
||||
nxtProcTable mProcs = {};
|
||||
// Get the initial render target and arbitrarily choose a "previous" render target
|
||||
// that's different
|
||||
mPreviousRenderTargetIndex = mRenderTargetIndex =
|
||||
mSwapChain->GetCurrentBackBufferIndex();
|
||||
mPreviousRenderTargetIndex = mRenderTargetIndex == 0 ? 1 : 0;
|
||||
|
||||
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)
|
||||
: mWindow(window), mProcs(procs), mFactory(CreateFactory()) {
|
||||
// Initial the serial for all render targets
|
||||
const uint64_t initialSerial = backend::d3d12::GetSerial(mBackendDevice);
|
||||
for (uint32_t n = 0; n < kFrameCount; ++n) {
|
||||
mLastSerialRenderTargetWasUsed[n] = initialSerial;
|
||||
}
|
||||
|
||||
~SwapChainImplD3D12() {
|
||||
return NXT_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
|
||||
nxtSwapChainError GetNextTexture(nxtSwapChainNextTexture* nextTexture) {
|
||||
nextTexture->texture = mRenderTargetResources[mRenderTargetIndex].Get();
|
||||
return NXT_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
|
||||
nxtSwapChainError Present() {
|
||||
// Current frame already transitioned to Present by the application, but
|
||||
// we need to flush the D3D12 backend's pending transitions.
|
||||
mProcs.deviceTick(mBackendDevice);
|
||||
|
||||
ASSERT_SUCCESS(mSwapChain->Present(1, 0));
|
||||
|
||||
// Transition last frame's render target back to being a render target
|
||||
if (mRenderTargetResourceState != D3D12_RESOURCE_STATE_PRESENT) {
|
||||
ComPtr<ID3D12GraphicsCommandList> commandList = {};
|
||||
backend::d3d12::OpenCommandList(mBackendDevice, &commandList);
|
||||
|
||||
D3D12_RESOURCE_BARRIER resourceBarrier;
|
||||
resourceBarrier.Transition.pResource =
|
||||
mRenderTargetResources[mPreviousRenderTargetIndex].Get();
|
||||
resourceBarrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
|
||||
resourceBarrier.Transition.StateAfter = mRenderTargetResourceState;
|
||||
resourceBarrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
resourceBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
resourceBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
commandList->ResourceBarrier(1, &resourceBarrier);
|
||||
ASSERT_SUCCESS(commandList->Close());
|
||||
backend::d3d12::ExecuteCommandLists(mBackendDevice, {commandList.Get()});
|
||||
}
|
||||
|
||||
// For GenerateSwapChainImplementation
|
||||
friend class SwapChainImpl;
|
||||
backend::d3d12::NextSerial(mBackendDevice);
|
||||
|
||||
void Init(nxtWSIContextD3D12* ctx) {
|
||||
mBackendDevice = ctx->device;
|
||||
mCommandQueue = backend::d3d12::GetCommandQueue(mBackendDevice);
|
||||
}
|
||||
mPreviousRenderTargetIndex = mRenderTargetIndex;
|
||||
mRenderTargetIndex = mSwapChain->GetCurrentBackBufferIndex();
|
||||
|
||||
nxtSwapChainError Configure(nxtTextureFormat format, nxtTextureUsageBit allowedUsage,
|
||||
uint32_t width, uint32_t height) {
|
||||
if (format != NXT_TEXTURE_FORMAT_R8_G8_B8_A8_UNORM) {
|
||||
return "unsupported format";
|
||||
}
|
||||
ASSERT(width > 0);
|
||||
ASSERT(height > 0);
|
||||
// If the next render target is not ready to be rendered yet, wait until it is ready.
|
||||
// If the last completed serial is less than the last requested serial for this render
|
||||
// target, then the commands previously executed on this render target have not yet
|
||||
// completed
|
||||
backend::d3d12::WaitForSerial(mBackendDevice,
|
||||
mLastSerialRenderTargetWasUsed[mRenderTargetIndex]);
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
|
||||
swapChainDesc.Width = width;
|
||||
swapChainDesc.Height = height;
|
||||
swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
swapChainDesc.BufferUsage = D3D12SwapChainBufferUsage(allowedUsage);
|
||||
swapChainDesc.BufferCount = kFrameCount;
|
||||
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
swapChainDesc.SampleDesc.Count = 1;
|
||||
swapChainDesc.SampleDesc.Quality = 0;
|
||||
mLastSerialRenderTargetWasUsed[mRenderTargetIndex] =
|
||||
backend::d3d12::GetSerial(mBackendDevice);
|
||||
|
||||
ComPtr<IDXGISwapChain1> swapChain1;
|
||||
ASSERT_SUCCESS(mFactory->CreateSwapChainForHwnd(
|
||||
mCommandQueue.Get(),
|
||||
mWindow,
|
||||
&swapChainDesc,
|
||||
nullptr,
|
||||
nullptr,
|
||||
&swapChain1
|
||||
));
|
||||
ASSERT_SUCCESS(swapChain1.As(&mSwapChain));
|
||||
|
||||
for (uint32_t n = 0; n < kFrameCount; ++n) {
|
||||
ASSERT_SUCCESS(mSwapChain->GetBuffer(n, IID_PPV_ARGS(&mRenderTargetResources[n])));
|
||||
}
|
||||
|
||||
// Get the initial render target and arbitrarily choose a "previous" render target that's different
|
||||
mPreviousRenderTargetIndex = mRenderTargetIndex = mSwapChain->GetCurrentBackBufferIndex();
|
||||
mPreviousRenderTargetIndex = mRenderTargetIndex == 0 ? 1 : 0;
|
||||
|
||||
// Initial the serial for all render targets
|
||||
const uint64_t initialSerial = backend::d3d12::GetSerial(mBackendDevice);
|
||||
for (uint32_t n = 0; n < kFrameCount; ++n) {
|
||||
mLastSerialRenderTargetWasUsed[n] = initialSerial;
|
||||
}
|
||||
|
||||
return NXT_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
|
||||
nxtSwapChainError GetNextTexture(nxtSwapChainNextTexture* nextTexture) {
|
||||
nextTexture->texture = mRenderTargetResources[mRenderTargetIndex].Get();
|
||||
return NXT_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
|
||||
nxtSwapChainError Present() {
|
||||
// Current frame already transitioned to Present by the application, but
|
||||
// we need to flush the D3D12 backend's pending transitions.
|
||||
mProcs.deviceTick(mBackendDevice);
|
||||
|
||||
ASSERT_SUCCESS(mSwapChain->Present(1, 0));
|
||||
|
||||
// Transition last frame's render target back to being a render target
|
||||
if (mRenderTargetResourceState != D3D12_RESOURCE_STATE_PRESENT) {
|
||||
ComPtr<ID3D12GraphicsCommandList> commandList = {};
|
||||
backend::d3d12::OpenCommandList(mBackendDevice, &commandList);
|
||||
|
||||
D3D12_RESOURCE_BARRIER resourceBarrier;
|
||||
resourceBarrier.Transition.pResource = mRenderTargetResources[mPreviousRenderTargetIndex].Get();
|
||||
resourceBarrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
|
||||
resourceBarrier.Transition.StateAfter = mRenderTargetResourceState;
|
||||
resourceBarrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
resourceBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
resourceBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
commandList->ResourceBarrier(1, &resourceBarrier);
|
||||
ASSERT_SUCCESS(commandList->Close());
|
||||
backend::d3d12::ExecuteCommandLists(mBackendDevice, { commandList.Get() });
|
||||
}
|
||||
|
||||
backend::d3d12::NextSerial(mBackendDevice);
|
||||
|
||||
mPreviousRenderTargetIndex = mRenderTargetIndex;
|
||||
mRenderTargetIndex = mSwapChain->GetCurrentBackBufferIndex();
|
||||
|
||||
// If the next render target is not ready to be rendered yet, wait until it is ready.
|
||||
// If the last completed serial is less than the last requested serial for this render target,
|
||||
// then the commands previously executed on this render target have not yet completed
|
||||
backend::d3d12::WaitForSerial(mBackendDevice, mLastSerialRenderTargetWasUsed[mRenderTargetIndex]);
|
||||
|
||||
mLastSerialRenderTargetWasUsed[mRenderTargetIndex] = backend::d3d12::GetSerial(mBackendDevice);
|
||||
|
||||
return NXT_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
return NXT_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
};
|
||||
|
||||
class D3D12Binding : public BackendBinding {
|
||||
public:
|
||||
void SetupGLFWWindowHints() override {
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
public:
|
||||
void SetupGLFWWindowHints() override {
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
}
|
||||
|
||||
void GetProcAndDevice(nxtProcTable* procs, nxtDevice* device) override {
|
||||
mFactory = CreateFactory();
|
||||
ASSERT(GetHardwareAdapter(mFactory.Get(), &mHardwareAdapter));
|
||||
ASSERT_SUCCESS(D3D12CreateDevice(mHardwareAdapter.Get(), D3D_FEATURE_LEVEL_11_0,
|
||||
IID_PPV_ARGS(&mD3d12Device)));
|
||||
|
||||
backend::d3d12::Init(mD3d12Device, procs, device);
|
||||
mBackendDevice = *device;
|
||||
mProcTable = *procs;
|
||||
}
|
||||
|
||||
uint64_t GetSwapChainImplementation() override {
|
||||
if (mSwapchainImpl.userData == nullptr) {
|
||||
HWND win32Window = glfwGetWin32Window(mWindow);
|
||||
mSwapchainImpl = SwapChainImplD3D12::Create(win32Window, mProcTable);
|
||||
}
|
||||
return reinterpret_cast<uint64_t>(&mSwapchainImpl);
|
||||
}
|
||||
|
||||
void GetProcAndDevice(nxtProcTable* procs, nxtDevice* device) override {
|
||||
mFactory = CreateFactory();
|
||||
ASSERT(GetHardwareAdapter(mFactory.Get(), &mHardwareAdapter));
|
||||
ASSERT_SUCCESS(D3D12CreateDevice(
|
||||
mHardwareAdapter.Get(),
|
||||
D3D_FEATURE_LEVEL_11_0,
|
||||
IID_PPV_ARGS(&mD3d12Device)
|
||||
));
|
||||
nxtTextureFormat GetPreferredSwapChainTextureFormat() override {
|
||||
return NXT_TEXTURE_FORMAT_R8_G8_B8_A8_UNORM;
|
||||
}
|
||||
|
||||
backend::d3d12::Init(mD3d12Device, procs, device);
|
||||
mBackendDevice = *device;
|
||||
mProcTable = *procs;
|
||||
}
|
||||
private:
|
||||
nxtDevice mBackendDevice = nullptr;
|
||||
nxtSwapChainImplementation mSwapchainImpl = {};
|
||||
nxtProcTable mProcTable = {};
|
||||
|
||||
uint64_t GetSwapChainImplementation() override {
|
||||
if (mSwapchainImpl.userData == nullptr) {
|
||||
HWND win32Window = glfwGetWin32Window(mWindow);
|
||||
mSwapchainImpl = SwapChainImplD3D12::Create(win32Window, mProcTable);
|
||||
// Initialization
|
||||
ComPtr<IDXGIFactory4> mFactory;
|
||||
ComPtr<IDXGIAdapter1> mHardwareAdapter;
|
||||
ComPtr<ID3D12Device> mD3d12Device;
|
||||
|
||||
static bool GetHardwareAdapter(IDXGIFactory4* factory, IDXGIAdapter1** hardwareAdapter) {
|
||||
*hardwareAdapter = nullptr;
|
||||
for (uint32_t adapterIndex = 0;; ++adapterIndex) {
|
||||
IDXGIAdapter1* adapter = nullptr;
|
||||
if (factory->EnumAdapters1(adapterIndex, &adapter) == DXGI_ERROR_NOT_FOUND) {
|
||||
break; // No more adapters to enumerate.
|
||||
}
|
||||
return reinterpret_cast<uint64_t>(&mSwapchainImpl);
|
||||
}
|
||||
|
||||
nxtTextureFormat GetPreferredSwapChainTextureFormat() override {
|
||||
return NXT_TEXTURE_FORMAT_R8_G8_B8_A8_UNORM;
|
||||
}
|
||||
|
||||
private:
|
||||
nxtDevice mBackendDevice = nullptr;
|
||||
nxtSwapChainImplementation mSwapchainImpl = {};
|
||||
nxtProcTable mProcTable = {};
|
||||
|
||||
// Initialization
|
||||
ComPtr<IDXGIFactory4> mFactory;
|
||||
ComPtr<IDXGIAdapter1> mHardwareAdapter;
|
||||
ComPtr<ID3D12Device> mD3d12Device;
|
||||
|
||||
static bool GetHardwareAdapter(IDXGIFactory4* factory, IDXGIAdapter1** hardwareAdapter) {
|
||||
*hardwareAdapter = nullptr;
|
||||
for (uint32_t adapterIndex = 0; ; ++adapterIndex) {
|
||||
IDXGIAdapter1* adapter = nullptr;
|
||||
if (factory->EnumAdapters1(adapterIndex, &adapter) == DXGI_ERROR_NOT_FOUND) {
|
||||
break; // No more adapters to enumerate.
|
||||
}
|
||||
|
||||
// Check to see if the adapter supports Direct3D 12, but don't create the actual device yet.
|
||||
if (SUCCEEDED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr))) {
|
||||
*hardwareAdapter = adapter;
|
||||
return true;
|
||||
}
|
||||
adapter->Release();
|
||||
// Check to see if the adapter supports Direct3D 12, but don't create the actual
|
||||
// device yet.
|
||||
if (SUCCEEDED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0,
|
||||
_uuidof(ID3D12Device), nullptr))) {
|
||||
*hardwareAdapter = adapter;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
adapter->Release();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
BackendBinding* CreateD3D12Binding() {
|
||||
return new D3D12Binding;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace utils
|
||||
|
||||
@@ -22,132 +22,130 @@
|
||||
#include "GLFW/glfw3.h"
|
||||
#include "GLFW/glfw3native.h"
|
||||
|
||||
#import <QuartzCore/CAMetalLayer.h>
|
||||
#import <Metal/Metal.h>
|
||||
#import <QuartzCore/CAMetalLayer.h>
|
||||
|
||||
namespace backend {
|
||||
namespace metal {
|
||||
namespace backend { namespace metal {
|
||||
void Init(id<MTLDevice> metalDevice, nxtProcTable* procs, nxtDevice* device);
|
||||
void SetNextDrawable(nxtDevice device, id<CAMetalDrawable> drawable);
|
||||
void Present(nxtDevice device);
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
namespace utils {
|
||||
class SwapChainImplMTL : SwapChainImpl {
|
||||
public:
|
||||
static nxtSwapChainImplementation Create(id nswindow) {
|
||||
auto impl = GenerateSwapChainImplementation<SwapChainImplMTL, nxtWSIContextMetal>();
|
||||
impl.userData = new SwapChainImplMTL(nswindow);
|
||||
return impl;
|
||||
public:
|
||||
static nxtSwapChainImplementation Create(id nswindow) {
|
||||
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() {
|
||||
[mCurrentTexture release];
|
||||
[mCurrentDrawable release];
|
||||
}
|
||||
|
||||
// For GenerateSwapChainImplementation
|
||||
friend class SwapChainImpl;
|
||||
|
||||
void Init(nxtWSIContextMetal* ctx) {
|
||||
mMtlDevice = ctx->device;
|
||||
mCommandQueue = [mMtlDevice newCommandQueue];
|
||||
}
|
||||
|
||||
nxtSwapChainError Configure(nxtTextureFormat format,
|
||||
nxtTextureUsageBit,
|
||||
uint32_t width,
|
||||
uint32_t height) {
|
||||
if (format != NXT_TEXTURE_FORMAT_B8_G8_R8_A8_UNORM) {
|
||||
return "unsupported format";
|
||||
}
|
||||
ASSERT(width > 0);
|
||||
ASSERT(height > 0);
|
||||
|
||||
private:
|
||||
id mNsWindow = nil;
|
||||
id<MTLDevice> mMtlDevice = nil;
|
||||
id<MTLCommandQueue> mCommandQueue = nil;
|
||||
NSView* contentView = [mNsWindow contentView];
|
||||
[contentView setWantsLayer:YES];
|
||||
|
||||
CAMetalLayer* mLayer = nullptr;
|
||||
id<CAMetalDrawable> mCurrentDrawable = nil;
|
||||
id<MTLTexture> mCurrentTexture = nil;
|
||||
CGSize size = {};
|
||||
size.width = width;
|
||||
size.height = height;
|
||||
|
||||
SwapChainImplMTL(id nsWindow)
|
||||
: mNsWindow(nsWindow) {
|
||||
}
|
||||
mLayer = [CAMetalLayer layer];
|
||||
[mLayer setDevice:mMtlDevice];
|
||||
[mLayer setPixelFormat:MTLPixelFormatBGRA8Unorm];
|
||||
[mLayer setFramebufferOnly:YES];
|
||||
[mLayer setDrawableSize:size];
|
||||
|
||||
~SwapChainImplMTL() {
|
||||
[mCurrentTexture release];
|
||||
[mCurrentDrawable release];
|
||||
}
|
||||
[contentView setLayer:mLayer];
|
||||
|
||||
// For GenerateSwapChainImplementation
|
||||
friend class SwapChainImpl;
|
||||
return NXT_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
|
||||
void Init(nxtWSIContextMetal* ctx) {
|
||||
mMtlDevice = ctx->device;
|
||||
mCommandQueue = [mMtlDevice newCommandQueue];
|
||||
}
|
||||
nxtSwapChainError GetNextTexture(nxtSwapChainNextTexture* nextTexture) {
|
||||
[mCurrentDrawable release];
|
||||
mCurrentDrawable = [mLayer nextDrawable];
|
||||
[mCurrentDrawable retain];
|
||||
|
||||
nxtSwapChainError Configure(nxtTextureFormat format, nxtTextureUsageBit,
|
||||
uint32_t width, uint32_t height) {
|
||||
if (format != NXT_TEXTURE_FORMAT_B8_G8_R8_A8_UNORM) {
|
||||
return "unsupported format";
|
||||
}
|
||||
ASSERT(width > 0);
|
||||
ASSERT(height > 0);
|
||||
[mCurrentTexture release];
|
||||
mCurrentTexture = mCurrentDrawable.texture;
|
||||
[mCurrentTexture retain];
|
||||
|
||||
NSView* contentView = [mNsWindow contentView];
|
||||
[contentView setWantsLayer: YES];
|
||||
nextTexture->texture = reinterpret_cast<void*>(mCurrentTexture);
|
||||
|
||||
CGSize size = {};
|
||||
size.width = width;
|
||||
size.height = height;
|
||||
return NXT_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
|
||||
mLayer = [CAMetalLayer layer];
|
||||
[mLayer setDevice: mMtlDevice];
|
||||
[mLayer setPixelFormat: MTLPixelFormatBGRA8Unorm];
|
||||
[mLayer setFramebufferOnly: YES];
|
||||
[mLayer setDrawableSize: size];
|
||||
nxtSwapChainError Present() {
|
||||
id<MTLCommandBuffer> commandBuffer = [mCommandQueue commandBuffer];
|
||||
[commandBuffer presentDrawable:mCurrentDrawable];
|
||||
[commandBuffer commit];
|
||||
|
||||
[contentView setLayer: mLayer];
|
||||
|
||||
return NXT_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
|
||||
nxtSwapChainError GetNextTexture(nxtSwapChainNextTexture* nextTexture) {
|
||||
[mCurrentDrawable release];
|
||||
mCurrentDrawable = [mLayer nextDrawable];
|
||||
[mCurrentDrawable retain];
|
||||
|
||||
[mCurrentTexture release];
|
||||
mCurrentTexture = mCurrentDrawable.texture;
|
||||
[mCurrentTexture retain];
|
||||
|
||||
nextTexture->texture = reinterpret_cast<void*>(mCurrentTexture);
|
||||
|
||||
return NXT_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
|
||||
nxtSwapChainError Present() {
|
||||
id<MTLCommandBuffer> commandBuffer = [mCommandQueue commandBuffer];
|
||||
[commandBuffer presentDrawable: mCurrentDrawable];
|
||||
[commandBuffer commit];
|
||||
|
||||
return NXT_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
return NXT_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
};
|
||||
|
||||
class MetalBinding : public BackendBinding {
|
||||
public:
|
||||
void SetupGLFWWindowHints() override {
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
}
|
||||
void GetProcAndDevice(nxtProcTable* procs, nxtDevice* device) override {
|
||||
mMetalDevice = MTLCreateSystemDefaultDevice();
|
||||
public:
|
||||
void SetupGLFWWindowHints() override {
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
}
|
||||
void GetProcAndDevice(nxtProcTable* procs, nxtDevice* device) override {
|
||||
mMetalDevice = MTLCreateSystemDefaultDevice();
|
||||
|
||||
backend::metal::Init(mMetalDevice, procs, device);
|
||||
mBackendDevice = *device;
|
||||
}
|
||||
backend::metal::Init(mMetalDevice, procs, device);
|
||||
mBackendDevice = *device;
|
||||
}
|
||||
|
||||
uint64_t GetSwapChainImplementation() override {
|
||||
if (mSwapchainImpl.userData == nullptr) {
|
||||
mSwapchainImpl = SwapChainImplMTL::Create(glfwGetCocoaWindow(mWindow));
|
||||
}
|
||||
return reinterpret_cast<uint64_t>(&mSwapchainImpl);
|
||||
uint64_t GetSwapChainImplementation() override {
|
||||
if (mSwapchainImpl.userData == nullptr) {
|
||||
mSwapchainImpl = SwapChainImplMTL::Create(glfwGetCocoaWindow(mWindow));
|
||||
}
|
||||
return reinterpret_cast<uint64_t>(&mSwapchainImpl);
|
||||
}
|
||||
|
||||
nxtTextureFormat GetPreferredSwapChainTextureFormat() override {
|
||||
return NXT_TEXTURE_FORMAT_B8_G8_R8_A8_UNORM;
|
||||
}
|
||||
nxtTextureFormat GetPreferredSwapChainTextureFormat() override {
|
||||
return NXT_TEXTURE_FORMAT_B8_G8_R8_A8_UNORM;
|
||||
}
|
||||
|
||||
private:
|
||||
id<MTLDevice> mMetalDevice = nil;
|
||||
nxtDevice mBackendDevice = nullptr;
|
||||
nxtSwapChainImplementation mSwapchainImpl = {};
|
||||
private:
|
||||
id<MTLDevice> mMetalDevice = nil;
|
||||
nxtDevice mBackendDevice = nullptr;
|
||||
nxtSwapChainImplementation mSwapchainImpl = {};
|
||||
};
|
||||
|
||||
BackendBinding* CreateMetalBinding() {
|
||||
return new MetalBinding;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
|
||||
namespace utils {
|
||||
|
||||
void FillShaderModuleBuilder(const nxt::ShaderModuleBuilder& builder, nxt::ShaderStage stage, const char* source) {
|
||||
void FillShaderModuleBuilder(const nxt::ShaderModuleBuilder& builder,
|
||||
nxt::ShaderStage stage,
|
||||
const char* source) {
|
||||
shaderc::Compiler compiler;
|
||||
shaderc::CompileOptions options;
|
||||
|
||||
@@ -60,7 +62,8 @@ namespace utils {
|
||||
|
||||
#ifdef DUMP_SPIRV_ASSEMBLY
|
||||
{
|
||||
auto resultAsm = compiler.CompileGlslToSpvAssembly(source, strlen(source), kind, "myshader?", options);
|
||||
auto resultAsm = compiler.CompileGlslToSpvAssembly(source, strlen(source), kind,
|
||||
"myshader?", options);
|
||||
size_t sizeAsm = (resultAsm.cend() - resultAsm.cbegin());
|
||||
|
||||
char* buffer = reinterpret_cast<char*>(malloc(sizeAsm + 1));
|
||||
@@ -86,21 +89,26 @@ namespace utils {
|
||||
#endif
|
||||
}
|
||||
|
||||
nxt::ShaderModule CreateShaderModule(const nxt::Device& device, nxt::ShaderStage stage, const char* source) {
|
||||
nxt::ShaderModule CreateShaderModule(const nxt::Device& device,
|
||||
nxt::ShaderStage stage,
|
||||
const char* source) {
|
||||
nxt::ShaderModuleBuilder builder = device.CreateShaderModuleBuilder();
|
||||
FillShaderModuleBuilder(builder, stage, source);
|
||||
return builder.GetResult();
|
||||
}
|
||||
|
||||
nxt::Buffer CreateFrozenBufferFromData(const nxt::Device& device, const void* data, uint32_t size, nxt::BufferUsageBit usage) {
|
||||
nxt::Buffer CreateFrozenBufferFromData(const nxt::Device& device,
|
||||
const void* data,
|
||||
uint32_t size,
|
||||
nxt::BufferUsageBit usage) {
|
||||
nxt::Buffer buffer = device.CreateBufferBuilder()
|
||||
.SetAllowedUsage(nxt::BufferUsageBit::TransferDst | usage)
|
||||
.SetInitialUsage(nxt::BufferUsageBit::TransferDst)
|
||||
.SetSize(size)
|
||||
.GetResult();
|
||||
.SetAllowedUsage(nxt::BufferUsageBit::TransferDst | usage)
|
||||
.SetInitialUsage(nxt::BufferUsageBit::TransferDst)
|
||||
.SetSize(size)
|
||||
.GetResult();
|
||||
buffer.SetSubData(0, size / sizeof(uint32_t), reinterpret_cast<const uint32_t*>(data));
|
||||
buffer.FreezeUsage(usage);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace utils
|
||||
|
||||
@@ -18,12 +18,23 @@
|
||||
|
||||
namespace utils {
|
||||
|
||||
void FillShaderModuleBuilder(const nxt::ShaderModuleBuilder& builder, nxt::ShaderStage stage, const char* source);
|
||||
nxt::ShaderModule CreateShaderModule(const nxt::Device& device, nxt::ShaderStage stage, const char* source);
|
||||
nxt::Buffer CreateFrozenBufferFromData(const nxt::Device& device, const void* data, uint32_t size, nxt::BufferUsageBit usage);
|
||||
void FillShaderModuleBuilder(const nxt::ShaderModuleBuilder& builder,
|
||||
nxt::ShaderStage stage,
|
||||
const char* source);
|
||||
nxt::ShaderModule CreateShaderModule(const nxt::Device& device,
|
||||
nxt::ShaderStage stage,
|
||||
const char* source);
|
||||
nxt::Buffer CreateFrozenBufferFromData(const nxt::Device& device,
|
||||
const void* data,
|
||||
uint32_t size,
|
||||
nxt::BufferUsageBit usage);
|
||||
|
||||
template<typename T>
|
||||
nxt::Buffer CreateFrozenBufferFromData(const nxt::Device& device, nxt::BufferUsageBit usage, std::initializer_list<T> data) {
|
||||
return CreateFrozenBufferFromData(device, data.begin(), uint32_t(sizeof(T) * data.size()), usage);
|
||||
template <typename T>
|
||||
nxt::Buffer CreateFrozenBufferFromData(const nxt::Device& device,
|
||||
nxt::BufferUsageBit usage,
|
||||
std::initializer_list<T> data) {
|
||||
return CreateFrozenBufferFromData(device, data.begin(), uint32_t(sizeof(T) * data.size()),
|
||||
usage);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
|
||||
@@ -14,32 +14,29 @@
|
||||
|
||||
#include "utils/BackendBinding.h"
|
||||
|
||||
namespace backend {
|
||||
namespace null {
|
||||
void Init(nxtProcTable* procs, nxtDevice* device);
|
||||
}
|
||||
}
|
||||
namespace backend { namespace null {
|
||||
void Init(nxtProcTable* procs, nxtDevice* device);
|
||||
}} // namespace backend::null
|
||||
|
||||
namespace utils {
|
||||
|
||||
class NullBinding : public BackendBinding {
|
||||
public:
|
||||
void SetupGLFWWindowHints() override {
|
||||
}
|
||||
void GetProcAndDevice(nxtProcTable* procs, nxtDevice* device) override {
|
||||
backend::null::Init(procs, device);
|
||||
}
|
||||
uint64_t GetSwapChainImplementation() override {
|
||||
return 0;
|
||||
}
|
||||
nxtTextureFormat GetPreferredSwapChainTextureFormat() override {
|
||||
return NXT_TEXTURE_FORMAT_R8_G8_B8_A8_UNORM;
|
||||
}
|
||||
public:
|
||||
void SetupGLFWWindowHints() override {
|
||||
}
|
||||
void GetProcAndDevice(nxtProcTable* procs, nxtDevice* device) override {
|
||||
backend::null::Init(procs, device);
|
||||
}
|
||||
uint64_t GetSwapChainImplementation() override {
|
||||
return 0;
|
||||
}
|
||||
nxtTextureFormat GetPreferredSwapChainTextureFormat() override {
|
||||
return NXT_TEXTURE_FORMAT_R8_G8_B8_A8_UNORM;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
BackendBinding* CreateNullBinding() {
|
||||
return new NullBinding;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace utils
|
||||
|
||||
@@ -19,130 +19,131 @@
|
||||
#include "nxt/nxt_wsi.h"
|
||||
#include "utils/SwapChainImpl.h"
|
||||
|
||||
#include <cstdio>
|
||||
// Glad needs to be included before GLFW otherwise it complain that GL.h was already included
|
||||
#include "glad/glad.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include "GLFW/glfw3.h"
|
||||
|
||||
namespace backend {
|
||||
namespace opengl {
|
||||
void Init(void* (*getProc)(const char*), nxtProcTable* procs, nxtDevice* device);
|
||||
}
|
||||
}
|
||||
namespace backend { namespace opengl {
|
||||
void Init(void* (*getProc)(const char*), nxtProcTable* procs, nxtDevice* device);
|
||||
}} // namespace backend::opengl
|
||||
|
||||
namespace utils {
|
||||
class SwapChainImplGL : SwapChainImpl {
|
||||
public:
|
||||
static nxtSwapChainImplementation Create(GLFWwindow* window) {
|
||||
auto impl = GenerateSwapChainImplementation<SwapChainImplGL, nxtWSIContextGL>();
|
||||
impl.userData = new SwapChainImplGL(window);
|
||||
return impl;
|
||||
public:
|
||||
static nxtSwapChainImplementation Create(GLFWwindow* window) {
|
||||
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() {
|
||||
glDeleteTextures(1, &mBackTexture);
|
||||
glDeleteFramebuffers(1, &mBackFBO);
|
||||
}
|
||||
|
||||
// For GenerateSwapChainImplementation
|
||||
friend class SwapChainImpl;
|
||||
|
||||
void Init(nxtWSIContextGL*) {
|
||||
glGenTextures(1, &mBackTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, mBackTexture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
|
||||
glGenFramebuffers(1, &mBackFBO);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, mBackFBO);
|
||||
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
||||
mBackTexture, 0);
|
||||
}
|
||||
|
||||
nxtSwapChainError Configure(nxtTextureFormat format,
|
||||
nxtTextureUsageBit,
|
||||
uint32_t width,
|
||||
uint32_t height) {
|
||||
if (format != NXT_TEXTURE_FORMAT_R8_G8_B8_A8_UNORM) {
|
||||
return "unsupported format";
|
||||
}
|
||||
ASSERT(width > 0);
|
||||
ASSERT(height > 0);
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
|
||||
private:
|
||||
GLFWwindow* mWindow = nullptr;
|
||||
uint32_t mWidth = 0;
|
||||
uint32_t mHeight = 0;
|
||||
GLuint mBackFBO = 0;
|
||||
GLuint mBackTexture = 0;
|
||||
glBindTexture(GL_TEXTURE_2D, mBackTexture);
|
||||
// Reallocate the texture
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
nullptr);
|
||||
|
||||
SwapChainImplGL(GLFWwindow* window)
|
||||
: mWindow(window) {
|
||||
}
|
||||
return NXT_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
|
||||
~SwapChainImplGL() {
|
||||
glDeleteTextures(1, &mBackTexture);
|
||||
glDeleteFramebuffers(1, &mBackFBO);
|
||||
}
|
||||
nxtSwapChainError GetNextTexture(nxtSwapChainNextTexture* nextTexture) {
|
||||
nextTexture->texture = reinterpret_cast<void*>(static_cast<size_t>(mBackTexture));
|
||||
return NXT_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
|
||||
// For GenerateSwapChainImplementation
|
||||
friend class SwapChainImpl;
|
||||
nxtSwapChainError Present() {
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, mBackFBO);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glBlitFramebuffer(0, 0, mWidth, mHeight, 0, 0, mWidth, mHeight, GL_COLOR_BUFFER_BIT,
|
||||
GL_NEAREST);
|
||||
glfwSwapBuffers(mWindow);
|
||||
|
||||
void Init(nxtWSIContextGL*) {
|
||||
glGenTextures(1, &mBackTexture);
|
||||
glBindTexture(GL_TEXTURE_2D, mBackTexture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
|
||||
glGenFramebuffers(1, &mBackFBO);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, mBackFBO);
|
||||
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
GL_TEXTURE_2D, mBackTexture, 0);
|
||||
}
|
||||
|
||||
nxtSwapChainError Configure(nxtTextureFormat format, nxtTextureUsageBit,
|
||||
uint32_t width, uint32_t height) {
|
||||
if (format != NXT_TEXTURE_FORMAT_R8_G8_B8_A8_UNORM) {
|
||||
return "unsupported format";
|
||||
}
|
||||
ASSERT(width > 0);
|
||||
ASSERT(height > 0);
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, mBackTexture);
|
||||
// Reallocate the texture
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
|
||||
return NXT_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
|
||||
nxtSwapChainError GetNextTexture(nxtSwapChainNextTexture* nextTexture) {
|
||||
nextTexture->texture = reinterpret_cast<void*>(static_cast<size_t>(mBackTexture));
|
||||
return NXT_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
|
||||
nxtSwapChainError Present() {
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, mBackFBO);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glBlitFramebuffer(0, 0, mWidth, mHeight, 0, 0, mWidth, mHeight,
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
glfwSwapBuffers(mWindow);
|
||||
|
||||
return NXT_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
return NXT_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
};
|
||||
|
||||
class OpenGLBinding : public BackendBinding {
|
||||
public:
|
||||
void SetupGLFWWindowHints() override {
|
||||
#if defined(NXT_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
|
||||
}
|
||||
void GetProcAndDevice(nxtProcTable* procs, nxtDevice* device) override {
|
||||
glfwMakeContextCurrent(mWindow);
|
||||
backend::opengl::Init(reinterpret_cast<void*(*)(const char*)>(glfwGetProcAddress), procs, device);
|
||||
public:
|
||||
void SetupGLFWWindowHints() override {
|
||||
#if defined(NXT_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
|
||||
}
|
||||
void GetProcAndDevice(nxtProcTable* procs, nxtDevice* device) override {
|
||||
glfwMakeContextCurrent(mWindow);
|
||||
backend::opengl::Init(reinterpret_cast<void* (*)(const char*)>(glfwGetProcAddress),
|
||||
procs, device);
|
||||
|
||||
mBackendDevice = *device;
|
||||
}
|
||||
mBackendDevice = *device;
|
||||
}
|
||||
|
||||
uint64_t GetSwapChainImplementation() override {
|
||||
if (mSwapchainImpl.userData == nullptr) {
|
||||
mSwapchainImpl = SwapChainImplGL::Create(mWindow);
|
||||
}
|
||||
return reinterpret_cast<uint64_t>(&mSwapchainImpl);
|
||||
uint64_t GetSwapChainImplementation() override {
|
||||
if (mSwapchainImpl.userData == nullptr) {
|
||||
mSwapchainImpl = SwapChainImplGL::Create(mWindow);
|
||||
}
|
||||
return reinterpret_cast<uint64_t>(&mSwapchainImpl);
|
||||
}
|
||||
|
||||
nxtTextureFormat GetPreferredSwapChainTextureFormat() override {
|
||||
return NXT_TEXTURE_FORMAT_R8_G8_B8_A8_UNORM;
|
||||
}
|
||||
nxtTextureFormat GetPreferredSwapChainTextureFormat() override {
|
||||
return NXT_TEXTURE_FORMAT_R8_G8_B8_A8_UNORM;
|
||||
}
|
||||
|
||||
private:
|
||||
nxtDevice mBackendDevice = nullptr;
|
||||
nxtSwapChainImplementation mSwapchainImpl = {};
|
||||
private:
|
||||
nxtDevice mBackendDevice = nullptr;
|
||||
nxtSwapChainImplementation mSwapchainImpl = {};
|
||||
};
|
||||
|
||||
BackendBinding* CreateOpenGLBinding() {
|
||||
return new OpenGLBinding;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace utils
|
||||
|
||||
@@ -17,30 +17,29 @@
|
||||
|
||||
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;
|
||||
}
|
||||
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_
|
||||
#endif // UTILS_SWAPCHAINIMPL_H_
|
||||
|
||||
@@ -15,25 +15,25 @@
|
||||
#include "common/Platform.h"
|
||||
|
||||
#if defined(NXT_PLATFORM_WINDOWS)
|
||||
#include <Windows.h>
|
||||
# include <Windows.h>
|
||||
#elif defined(NXT_PLATFORM_POSIX)
|
||||
#include <unistd.h>
|
||||
# include <unistd.h>
|
||||
#else
|
||||
#error "Unsupported platform."
|
||||
# error "Unsupported platform."
|
||||
#endif
|
||||
|
||||
namespace utils {
|
||||
|
||||
#if defined(NXT_PLATFORM_WINDOWS)
|
||||
void USleep(unsigned int usecs) {
|
||||
Sleep(static_cast<DWORD>(usecs / 1000));
|
||||
}
|
||||
#elif defined(NXT_PLATFORM_POSIX)
|
||||
void USleep(unsigned int usecs) {
|
||||
usleep(usecs);
|
||||
}
|
||||
#else
|
||||
#error "Implement USleep for your platform."
|
||||
#endif
|
||||
#if defined(NXT_PLATFORM_WINDOWS)
|
||||
void USleep(unsigned int usecs) {
|
||||
Sleep(static_cast<DWORD>(usecs / 1000));
|
||||
}
|
||||
#elif defined(NXT_PLATFORM_POSIX)
|
||||
void USleep(unsigned int usecs) {
|
||||
usleep(usecs);
|
||||
}
|
||||
#else
|
||||
# error "Implement USleep for your platform."
|
||||
#endif
|
||||
|
||||
}
|
||||
} // namespace utils
|
||||
|
||||
@@ -15,5 +15,4 @@
|
||||
namespace utils {
|
||||
|
||||
void USleep(unsigned int usecs);
|
||||
|
||||
}
|
||||
|
||||
@@ -17,75 +17,71 @@
|
||||
#include "nxt/nxt_wsi.h"
|
||||
#include "utils/SwapChainImpl.h"
|
||||
|
||||
namespace backend {
|
||||
namespace vulkan {
|
||||
void Init(nxtProcTable* procs, nxtDevice* device);
|
||||
}
|
||||
}
|
||||
namespace backend { namespace vulkan {
|
||||
void Init(nxtProcTable* procs, nxtDevice* device);
|
||||
}} // namespace backend::vulkan
|
||||
|
||||
namespace utils {
|
||||
|
||||
class SwapChainImplVulkan : SwapChainImpl {
|
||||
public:
|
||||
static nxtSwapChainImplementation Create(GLFWwindow* window) {
|
||||
auto impl = GenerateSwapChainImplementation<SwapChainImplVulkan, nxtWSIContextVulkan>();
|
||||
impl.userData = new SwapChainImplVulkan(window);
|
||||
return impl;
|
||||
}
|
||||
public:
|
||||
static nxtSwapChainImplementation Create(GLFWwindow* window) {
|
||||
auto impl = GenerateSwapChainImplementation<SwapChainImplVulkan, nxtWSIContextVulkan>();
|
||||
impl.userData = new SwapChainImplVulkan(window);
|
||||
return impl;
|
||||
}
|
||||
|
||||
private:
|
||||
GLFWwindow* window = nullptr;
|
||||
private:
|
||||
GLFWwindow* window = nullptr;
|
||||
|
||||
SwapChainImplVulkan(GLFWwindow* window)
|
||||
: window(window) {
|
||||
}
|
||||
SwapChainImplVulkan(GLFWwindow* window) : window(window) {
|
||||
}
|
||||
|
||||
~SwapChainImplVulkan() {
|
||||
}
|
||||
~SwapChainImplVulkan() {
|
||||
}
|
||||
|
||||
// For GenerateSwapChainImplementation
|
||||
friend class SwapChainImpl;
|
||||
// For GenerateSwapChainImplementation
|
||||
friend class SwapChainImpl;
|
||||
|
||||
void Init(nxtWSIContextVulkan*) {
|
||||
}
|
||||
void Init(nxtWSIContextVulkan*) {
|
||||
}
|
||||
|
||||
nxtSwapChainError Configure(nxtTextureFormat, nxtTextureUsageBit, uint32_t, uint32_t) {
|
||||
return NXT_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
nxtSwapChainError Configure(nxtTextureFormat, nxtTextureUsageBit, uint32_t, uint32_t) {
|
||||
return NXT_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
|
||||
nxtSwapChainError GetNextTexture(nxtSwapChainNextTexture*) {
|
||||
return NXT_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
nxtSwapChainError GetNextTexture(nxtSwapChainNextTexture*) {
|
||||
return NXT_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
|
||||
nxtSwapChainError Present() {
|
||||
return NXT_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
nxtSwapChainError Present() {
|
||||
return NXT_SWAP_CHAIN_NO_ERROR;
|
||||
}
|
||||
};
|
||||
|
||||
class VulkanBinding : public BackendBinding {
|
||||
public:
|
||||
void SetupGLFWWindowHints() override {
|
||||
}
|
||||
void GetProcAndDevice(nxtProcTable* procs, nxtDevice* device) override {
|
||||
backend::vulkan::Init(procs, device);
|
||||
}
|
||||
uint64_t GetSwapChainImplementation() override {
|
||||
if (mSwapchainImpl.userData == nullptr) {
|
||||
mSwapchainImpl = SwapChainImplVulkan::Create(mWindow);
|
||||
}
|
||||
return reinterpret_cast<uint64_t>(&mSwapchainImpl);
|
||||
}
|
||||
nxtTextureFormat GetPreferredSwapChainTextureFormat() override {
|
||||
return NXT_TEXTURE_FORMAT_R8_G8_B8_A8_UNORM;
|
||||
public:
|
||||
void SetupGLFWWindowHints() override {
|
||||
}
|
||||
void GetProcAndDevice(nxtProcTable* procs, nxtDevice* device) override {
|
||||
backend::vulkan::Init(procs, device);
|
||||
}
|
||||
uint64_t GetSwapChainImplementation() override {
|
||||
if (mSwapchainImpl.userData == nullptr) {
|
||||
mSwapchainImpl = SwapChainImplVulkan::Create(mWindow);
|
||||
}
|
||||
return reinterpret_cast<uint64_t>(&mSwapchainImpl);
|
||||
}
|
||||
nxtTextureFormat GetPreferredSwapChainTextureFormat() override {
|
||||
return NXT_TEXTURE_FORMAT_R8_G8_B8_A8_UNORM;
|
||||
}
|
||||
|
||||
private:
|
||||
nxtSwapChainImplementation mSwapchainImpl = {};
|
||||
private:
|
||||
nxtSwapChainImplementation mSwapchainImpl = {};
|
||||
};
|
||||
|
||||
|
||||
BackendBinding* CreateVulkanBinding() {
|
||||
return new VulkanBinding;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace utils
|
||||
|
||||
Reference in New Issue
Block a user