mirror of https://github.com/AxioDL/metaforce.git
aurora: Dawn + SDL united at last
This commit is contained in:
parent
aabef3e058
commit
e866245f60
|
@ -9,8 +9,23 @@ if (NOT MSVC)
|
||||||
target_compile_options(SPIRV-Tools-opt PRIVATE -Wno-implicit-fallthrough)
|
target_compile_options(SPIRV-Tools-opt PRIVATE -Wno-implicit-fallthrough)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
add_library(aurora STATIC lib/aurora.cpp lib/imgui.cpp lib/gfx/common.cpp)
|
add_library(aurora STATIC
|
||||||
|
lib/aurora.cpp
|
||||||
|
lib/imgui.cpp
|
||||||
|
lib/dawn/BackendBinding.cpp
|
||||||
|
lib/gfx/common.cpp
|
||||||
|
)
|
||||||
target_include_directories(aurora PUBLIC include ../Runtime)
|
target_include_directories(aurora PUBLIC include ../Runtime)
|
||||||
target_include_directories(aurora PRIVATE ../imgui ../extern/imgui)
|
target_include_directories(aurora PRIVATE ../imgui ../extern/imgui)
|
||||||
target_link_libraries(aurora PRIVATE dawn_native dawncpp webgpu_dawn zeus logvisor SDL2-static)
|
target_link_libraries(aurora PRIVATE dawn_native dawncpp webgpu_dawn zeus logvisor SDL2-static)
|
||||||
target_compile_definitions(aurora PRIVATE AURORA_ENABLE_VULKAN AURORA_ENABLE_OPENGL)
|
if (APPLE)
|
||||||
|
target_compile_definitions(aurora PRIVATE DAWN_ENABLE_BACKEND_METAL)
|
||||||
|
target_sources(aurora PRIVATE lib/dawn/MetalBinding.mm)
|
||||||
|
set_source_files_properties(lib/dawn/MetalBinding.mm PROPERTIES COMPILE_FLAGS -fobjc-arc)
|
||||||
|
else ()
|
||||||
|
target_compile_definitions(aurora PRIVATE
|
||||||
|
DAWN_ENABLE_BACKEND_VULKAN
|
||||||
|
DAWN_ENABLE_BACKEND_OPENGL
|
||||||
|
DAWN_ENABLE_BACKEND_DESKTOP_GL)
|
||||||
|
target_sources(aurora PRIVATE lib/dawn/OpenGLBinding.cpp lib/dawn/VulkanBinding.cpp)
|
||||||
|
endif ()
|
||||||
|
|
|
@ -182,6 +182,7 @@ enum class Backend : uint8_t {
|
||||||
D3D12,
|
D3D12,
|
||||||
D3D11,
|
D3D11,
|
||||||
OpenGL,
|
OpenGL,
|
||||||
|
OpenGLES,
|
||||||
WebGPU,
|
WebGPU,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,40 +1,51 @@
|
||||||
#include <SDL.h>
|
|
||||||
#include <aurora/aurora.hpp>
|
#include <aurora/aurora.hpp>
|
||||||
#include <logvisor/logvisor.hpp>
|
|
||||||
#include <memory>
|
#include <SDL.h>
|
||||||
#include <dawn/native/DawnNative.h>
|
#include <dawn/native/DawnNative.h>
|
||||||
#ifdef AURORA_ENABLE_VULKAN
|
#include <dawn/webgpu_cpp.h>
|
||||||
|
#include <logvisor/logvisor.hpp>
|
||||||
|
#include <magic_enum.hpp>
|
||||||
|
|
||||||
|
#ifdef DAWN_ENABLE_BACKEND_VULKAN
|
||||||
#include <SDL_vulkan.h>
|
#include <SDL_vulkan.h>
|
||||||
#include <dawn/native/VulkanBackend.h>
|
#include <dawn/native/VulkanBackend.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef AURORA_ENABLE_OPENGL
|
#ifdef DAWN_ENABLE_BACKEND_OPENGL
|
||||||
#include <SDL_opengl.h>
|
#include <SDL_opengl.h>
|
||||||
#include <dawn/native/OpenGLBackend.h>
|
#include <dawn/native/OpenGLBackend.h>
|
||||||
#endif
|
#endif
|
||||||
#include <dawn/webgpu_cpp.h>
|
#ifdef DAWN_ENABLE_BACKEND_METAL
|
||||||
#include <magic_enum.hpp>
|
#include <SDL_metal.h>
|
||||||
|
#include <dawn/native/MetalBackend.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "dawn/BackendBinding.hpp"
|
||||||
|
|
||||||
namespace aurora {
|
namespace aurora {
|
||||||
// TODO: Move global state to a class/struct?
|
// TODO: Move global state to a class/struct?
|
||||||
static logvisor::Module Log("aurora");
|
static logvisor::Module Log("aurora");
|
||||||
|
|
||||||
static std::unique_ptr<AppDelegate> g_AppDelegate;
|
static std::unique_ptr<AppDelegate> g_AppDelegate;
|
||||||
|
static std::vector<std::string> g_Args;
|
||||||
|
|
||||||
// SDL
|
// SDL
|
||||||
static SDL_Window* g_Window;
|
static SDL_Window* g_Window;
|
||||||
|
|
||||||
// Dawn / WebGPU
|
// Dawn / WebGPU
|
||||||
#ifdef AURORA_ENABLE_VULKAN
|
#ifdef DAWN_ENABLE_BACKEND_VULKAN
|
||||||
static wgpu::BackendType backendType = wgpu::BackendType::Vulkan;
|
static wgpu::BackendType preferredBackendType = wgpu::BackendType::Vulkan;
|
||||||
#elif AURORA_ENABLE_METAL
|
#elif DAWN_ENABLE_BACKEND_METAL
|
||||||
static wgpu::BackendType backendType = wgpu::BackendType::Metal;
|
static wgpu::BackendType preferredBackendType = wgpu::BackendType::Metal;
|
||||||
#else
|
#else
|
||||||
static wgpu::BackendType backendType = wgpu::BackendType::OpenGL;
|
static wgpu::BackendType preferredBackendType = wgpu::BackendType::OpenGL;
|
||||||
#endif
|
#endif
|
||||||
static std::vector<std::string> g_Args;
|
static std::unique_ptr<dawn::native::Instance> g_Instance;
|
||||||
static wgpu::SwapChain g_SwapChain;
|
static dawn::native::Adapter g_Adapter;
|
||||||
static DawnSwapChainImplementation g_SwapChainImpl;
|
static wgpu::AdapterProperties g_AdapterProperties;
|
||||||
static wgpu::Queue g_Queue;
|
|
||||||
static wgpu::Device g_Device;
|
static wgpu::Device g_Device;
|
||||||
static wgpu::TextureFormat g_SwapChainFormat;
|
static wgpu::Queue g_Queue;
|
||||||
|
static wgpu::SwapChain g_SwapChain;
|
||||||
|
static std::unique_ptr<utils::BackendBinding> g_BackendBinding;
|
||||||
|
|
||||||
static void set_window_icon(Icon icon) noexcept {
|
static void set_window_icon(Icon icon) noexcept {
|
||||||
SDL_Surface* iconSurface = SDL_CreateRGBSurfaceFrom(icon.data.get(), icon.width, icon.height, 32, 4 * icon.width,
|
SDL_Surface* iconSurface = SDL_CreateRGBSurfaceFrom(icon.data.get(), icon.width, icon.height, 32, 4 * icon.width,
|
||||||
|
@ -182,45 +193,23 @@ void app_run(std::unique_ptr<AppDelegate> app, Icon icon, int argc, char** argv)
|
||||||
g_Args.emplace_back(argv[i]);
|
g_Args.emplace_back(argv[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.report(logvisor::Info, FMT_STRING("Creating Dawn instance"));
|
|
||||||
auto instance = std::make_unique<dawn::native::Instance>();
|
|
||||||
instance->DiscoverDefaultAdapters();
|
|
||||||
|
|
||||||
dawn::native::Adapter backendAdapter;
|
|
||||||
{
|
|
||||||
std::vector<dawn::native::Adapter> adapters = instance->GetAdapters();
|
|
||||||
auto adapterIt = std::find_if(adapters.begin(), adapters.end(), [](const dawn::native::Adapter adapter) -> bool {
|
|
||||||
wgpu::AdapterProperties properties;
|
|
||||||
adapter.GetProperties(&properties);
|
|
||||||
return properties.backendType == backendType;
|
|
||||||
});
|
|
||||||
if (adapterIt == adapters.end()) {
|
|
||||||
Log.report(logvisor::Fatal, FMT_STRING("Failed to find usable graphics backend"));
|
|
||||||
}
|
|
||||||
backendAdapter = *adapterIt;
|
|
||||||
}
|
|
||||||
wgpu::AdapterProperties adapterProperties;
|
|
||||||
backendAdapter.GetProperties(&adapterProperties);
|
|
||||||
const auto backendName = magic_enum::enum_name(adapterProperties.backendType);
|
|
||||||
Log.report(logvisor::Info, FMT_STRING("Using {} graphics backend"), backendName);
|
|
||||||
|
|
||||||
if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
|
if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
|
||||||
Log.report(logvisor::Fatal, FMT_STRING("Error initializing SDL: {}"), SDL_GetError());
|
Log.report(logvisor::Fatal, FMT_STRING("Error initializing SDL: {}"), SDL_GetError());
|
||||||
}
|
}
|
||||||
|
|
||||||
Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI;
|
Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_RESIZABLE;
|
||||||
switch (adapterProperties.backendType) {
|
switch (preferredBackendType) {
|
||||||
#ifdef AURORA_ENABLE_VULKAN
|
#ifdef DAWN_ENABLE_BACKEND_VULKAN
|
||||||
case wgpu::BackendType::Vulkan:
|
case wgpu::BackendType::Vulkan:
|
||||||
flags |= SDL_WINDOW_VULKAN;
|
flags |= SDL_WINDOW_VULKAN;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef AURORA_ENABLE_METAL
|
#ifdef DAWN_ENABLE_BACKEND_METAL
|
||||||
case wgpu::BackendType::Metal:
|
case wgpu::BackendType::Metal:
|
||||||
flags |= SDL_WINDOW_METAL;
|
flags |= SDL_WINDOW_METAL;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef AURORA_ENABLE_OPENGL
|
#ifdef DAWN_ENABLE_BACKEND_OPENGL
|
||||||
case wgpu::BackendType::OpenGL:
|
case wgpu::BackendType::OpenGL:
|
||||||
flags |= SDL_WINDOW_OPENGL;
|
flags |= SDL_WINDOW_OPENGL;
|
||||||
break;
|
break;
|
||||||
|
@ -234,59 +223,74 @@ void app_run(std::unique_ptr<AppDelegate> app, Icon icon, int argc, char** argv)
|
||||||
}
|
}
|
||||||
set_window_icon(std::move(icon));
|
set_window_icon(std::move(icon));
|
||||||
|
|
||||||
g_Device = wgpu::Device::Acquire(backendAdapter.CreateDevice());
|
Log.report(logvisor::Info, FMT_STRING("Creating Dawn instance"));
|
||||||
switch (adapterProperties.backendType) {
|
g_Instance = std::make_unique<dawn::native::Instance>();
|
||||||
#ifdef AURORA_ENABLE_VULKAN
|
utils::DiscoverAdapter(g_Instance.get(), g_Window, preferredBackendType);
|
||||||
case wgpu::BackendType::Vulkan: {
|
|
||||||
VkSurfaceKHR surface = VK_NULL_HANDLE;
|
{
|
||||||
if (SDL_Vulkan_CreateSurface(g_Window, dawn::native::vulkan::GetInstance(g_Device.Get()), &surface) != SDL_TRUE) {
|
std::vector<dawn::native::Adapter> adapters = g_Instance->GetAdapters();
|
||||||
Log.report(logvisor::Fatal, FMT_STRING("Failed to create Vulkan surface: {}"), SDL_GetError());
|
auto adapterIt = std::find_if(adapters.begin(), adapters.end(), [](const dawn::native::Adapter adapter) -> bool {
|
||||||
|
wgpu::AdapterProperties properties;
|
||||||
|
adapter.GetProperties(&properties);
|
||||||
|
return properties.backendType == preferredBackendType;
|
||||||
|
});
|
||||||
|
if (adapterIt == adapters.end()) {
|
||||||
|
Log.report(logvisor::Fatal, FMT_STRING("Failed to find usable graphics backend"));
|
||||||
}
|
}
|
||||||
g_SwapChainImpl = dawn::native::vulkan::CreateNativeSwapChainImpl(g_Device.Get(), surface);
|
g_Adapter = *adapterIt;
|
||||||
g_SwapChainFormat =
|
|
||||||
static_cast<wgpu::TextureFormat>(dawn::native::vulkan::GetNativeSwapChainPreferredFormat(&g_SwapChainImpl));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
#endif
|
g_Adapter.GetProperties(&g_AdapterProperties);
|
||||||
#ifdef AURORA_ENABLE_METAL
|
const auto backendName = magic_enum::enum_name(g_AdapterProperties.backendType);
|
||||||
case wgpu::BackendType::Metal: {
|
Log.report(logvisor::Info, FMT_STRING("Using {} graphics backend"), backendName);
|
||||||
// TODO
|
|
||||||
g_SwapChainFormat = WGPUTextureFormat_BGRA8Unorm;
|
g_Device = wgpu::Device::Acquire(g_Adapter.CreateDevice());
|
||||||
break;
|
g_BackendBinding = std::unique_ptr<utils::BackendBinding>(
|
||||||
}
|
utils::CreateBinding(g_AdapterProperties.backendType, g_Window, g_Device.Get()));
|
||||||
#endif
|
if (!g_BackendBinding) {
|
||||||
#ifdef AURORA_ENABLE_OPENGL
|
|
||||||
case wgpu::BackendType::OpenGL: {
|
|
||||||
g_SwapChainImpl = dawn::native::opengl::CreateNativeSwapChainImpl(
|
|
||||||
g_Device.Get(), [](void* userdata) { SDL_GL_SwapWindow(static_cast<SDL_Window*>(userdata)); }, g_Window);
|
|
||||||
g_SwapChainFormat =
|
|
||||||
static_cast<wgpu::TextureFormat>(dawn::native::opengl::GetNativeSwapChainPreferredFormat(&g_SwapChainImpl));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
Log.report(logvisor::Fatal, FMT_STRING("Unsupported backend {}"), backendName);
|
Log.report(logvisor::Fatal, FMT_STRING("Unsupported backend {}"), backendName);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_Queue = g_Device.GetQueue();
|
g_Queue = g_Device.GetQueue();
|
||||||
{
|
{
|
||||||
wgpu::SwapChainDescriptor descriptor{};
|
wgpu::SwapChainDescriptor descriptor{};
|
||||||
descriptor.implementation = reinterpret_cast<uint64_t>(&g_SwapChainImpl);
|
descriptor.implementation = g_BackendBinding->GetSwapChainImplementation();
|
||||||
g_SwapChain = g_Device.CreateSwapChain(nullptr, &descriptor);
|
g_SwapChain = g_Device.CreateSwapChain(nullptr, &descriptor);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
int width, height;
|
auto size = get_window_size();
|
||||||
SDL_GetWindowSize(g_Window, &width, &height);
|
auto format = static_cast<wgpu::TextureFormat>(g_BackendBinding->GetPreferredSwapChainTextureFormat());
|
||||||
g_SwapChain.Configure(g_SwapChainFormat, wgpu::TextureUsage::RenderAttachment, width, height);
|
g_SwapChain.Configure(format, wgpu::TextureUsage::RenderAttachment, size.width, size.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_AppDelegate->onAppLaunched();
|
g_AppDelegate->onAppLaunched();
|
||||||
g_AppDelegate->onAppWindowResized(get_window_size());
|
g_AppDelegate->onAppWindowResized(get_window_size());
|
||||||
while (poll_events()) {}
|
while (poll_events()) {
|
||||||
|
auto encoder = g_Device.CreateCommandEncoder();
|
||||||
|
{
|
||||||
|
std::array<wgpu::RenderPassColorAttachment, 1> attachments{wgpu::RenderPassColorAttachment{
|
||||||
|
.view = g_SwapChain.GetCurrentTextureView(),
|
||||||
|
.loadOp = wgpu::LoadOp::Clear,
|
||||||
|
.storeOp = wgpu::StoreOp::Store,
|
||||||
|
.clearColor = {0.5f, 0.5f, 0.5f, 1.f},
|
||||||
|
}};
|
||||||
|
auto renderPassDescriptor = wgpu::RenderPassDescriptor{
|
||||||
|
.label = "Render Pass",
|
||||||
|
.colorAttachmentCount = attachments.size(),
|
||||||
|
.colorAttachments = attachments.data(),
|
||||||
|
};
|
||||||
|
auto pass = encoder.BeginRenderPass(&renderPassDescriptor);
|
||||||
|
pass.End();
|
||||||
|
}
|
||||||
|
const auto buffer = encoder.Finish();
|
||||||
|
g_Queue.Submit(1, &buffer);
|
||||||
|
g_SwapChain.Present();
|
||||||
|
}
|
||||||
|
|
||||||
g_SwapChain.Release();
|
wgpuSwapChainRelease(g_SwapChain.Release());
|
||||||
g_Queue.Release();
|
wgpuQueueRelease(g_Queue.Release());
|
||||||
g_Device.Release();
|
g_BackendBinding.reset();
|
||||||
|
wgpuDeviceRelease(g_Device.Release());
|
||||||
|
g_Instance.reset();
|
||||||
SDL_DestroyWindow(g_Window);
|
SDL_DestroyWindow(g_Window);
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
}
|
}
|
||||||
|
@ -299,7 +303,7 @@ WindowSize get_window_size() noexcept {
|
||||||
}
|
}
|
||||||
void set_window_title(zstring_view title) noexcept { SDL_SetWindowTitle(g_Window, title.c_str()); }
|
void set_window_title(zstring_view title) noexcept { SDL_SetWindowTitle(g_Window, title.c_str()); }
|
||||||
Backend get_backend() noexcept {
|
Backend get_backend() noexcept {
|
||||||
switch (backendType) {
|
switch (g_AdapterProperties.backendType) {
|
||||||
case wgpu::BackendType::WebGPU:
|
case wgpu::BackendType::WebGPU:
|
||||||
return Backend::WebGPU;
|
return Backend::WebGPU;
|
||||||
case wgpu::BackendType::D3D11:
|
case wgpu::BackendType::D3D11:
|
||||||
|
@ -311,13 +315,14 @@ Backend get_backend() noexcept {
|
||||||
case wgpu::BackendType::Vulkan:
|
case wgpu::BackendType::Vulkan:
|
||||||
return Backend::Vulkan;
|
return Backend::Vulkan;
|
||||||
case wgpu::BackendType::OpenGL:
|
case wgpu::BackendType::OpenGL:
|
||||||
case wgpu::BackendType::OpenGLES:
|
|
||||||
return Backend::OpenGL;
|
return Backend::OpenGL;
|
||||||
|
case wgpu::BackendType::OpenGLES:
|
||||||
|
return Backend::OpenGLES;
|
||||||
default:
|
default:
|
||||||
return Backend::Invalid;
|
return Backend::Invalid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string_view get_backend_string() noexcept { return magic_enum::enum_name(get_backend()); }
|
std::string_view get_backend_string() noexcept { return magic_enum::enum_name(g_AdapterProperties.backendType); }
|
||||||
void set_fullscreen(bool fullscreen) noexcept {
|
void set_fullscreen(bool fullscreen) noexcept {
|
||||||
auto flags = SDL_GetWindowFlags(g_Window);
|
auto flags = SDL_GetWindowFlags(g_Window);
|
||||||
if (fullscreen) {
|
if (fullscreen) {
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
#include "BackendBinding.hpp"
|
||||||
|
|
||||||
|
#if defined(DAWN_ENABLE_BACKEND_OPENGL)
|
||||||
|
#include <SDL_video.h>
|
||||||
|
#include <dawn/native/OpenGLBackend.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace aurora::utils {
|
||||||
|
|
||||||
|
#if defined(DAWN_ENABLE_BACKEND_D3D12)
|
||||||
|
BackendBinding* CreateD3D12Binding(SDL_Window* window, WGPUDevice device);
|
||||||
|
#endif
|
||||||
|
#if defined(DAWN_ENABLE_BACKEND_METAL)
|
||||||
|
BackendBinding* CreateMetalBinding(SDL_Window* window, WGPUDevice device);
|
||||||
|
#endif
|
||||||
|
#if defined(DAWN_ENABLE_BACKEND_NULL)
|
||||||
|
BackendBinding* CreateNullBinding(SDL_Window* window, WGPUDevice device);
|
||||||
|
#endif
|
||||||
|
#if defined(DAWN_ENABLE_BACKEND_OPENGL)
|
||||||
|
BackendBinding* CreateOpenGLBinding(SDL_Window* window, WGPUDevice device);
|
||||||
|
#endif
|
||||||
|
#if defined(DAWN_ENABLE_BACKEND_VULKAN)
|
||||||
|
BackendBinding* CreateVulkanBinding(SDL_Window* window, WGPUDevice device);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
BackendBinding::BackendBinding(SDL_Window* window, WGPUDevice device) : m_window(window), m_device(device) {}
|
||||||
|
|
||||||
|
void DiscoverAdapter(dawn::native::Instance* instance, SDL_Window* window, wgpu::BackendType type) {
|
||||||
|
if (type == wgpu::BackendType::OpenGL || type == wgpu::BackendType::OpenGLES) {
|
||||||
|
#if defined(DAWN_ENABLE_BACKEND_OPENGL)
|
||||||
|
SDL_GL_CreateContext(window);
|
||||||
|
auto getProc = reinterpret_cast<void* (*)(const char*)>(SDL_GL_GetProcAddress);
|
||||||
|
if (type == wgpu::BackendType::OpenGL) {
|
||||||
|
dawn::native::opengl::AdapterDiscoveryOptions adapterOptions;
|
||||||
|
adapterOptions.getProc = getProc;
|
||||||
|
instance->DiscoverAdapters(&adapterOptions);
|
||||||
|
} else {
|
||||||
|
dawn::native::opengl::AdapterDiscoveryOptionsES adapterOptions;
|
||||||
|
adapterOptions.getProc = getProc;
|
||||||
|
instance->DiscoverAdapters(&adapterOptions);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
instance->DiscoverDefaultAdapters();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BackendBinding* CreateBinding(wgpu::BackendType type, SDL_Window* window, WGPUDevice device) {
|
||||||
|
switch (type) {
|
||||||
|
#if defined(DAWN_ENABLE_BACKEND_D3D12)
|
||||||
|
case wgpu::BackendType::D3D12:
|
||||||
|
return CreateD3D12Binding(window, device);
|
||||||
|
#endif
|
||||||
|
#if defined(DAWN_ENABLE_BACKEND_METAL)
|
||||||
|
case wgpu::BackendType::Metal:
|
||||||
|
return CreateMetalBinding(window, device);
|
||||||
|
#endif
|
||||||
|
#if defined(DAWN_ENABLE_BACKEND_NULL)
|
||||||
|
case wgpu::BackendType::Null:
|
||||||
|
return CreateNullBinding(window, device);
|
||||||
|
#endif
|
||||||
|
#if defined(DAWN_ENABLE_BACKEND_DESKTOP_GL)
|
||||||
|
case wgpu::BackendType::OpenGL:
|
||||||
|
return CreateOpenGLBinding(window, device);
|
||||||
|
#endif
|
||||||
|
#if defined(DAWN_ENABLE_BACKEND_OPENGLES)
|
||||||
|
case wgpu::BackendType::OpenGLES:
|
||||||
|
return CreateOpenGLBinding(window, device);
|
||||||
|
#endif
|
||||||
|
#if defined(DAWN_ENABLE_BACKEND_VULKAN)
|
||||||
|
case wgpu::BackendType::Vulkan:
|
||||||
|
return CreateVulkanBinding(window, device);
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace aurora::utils
|
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <dawn/native/DawnNative.h>
|
||||||
|
#include <dawn/webgpu_cpp.h>
|
||||||
|
|
||||||
|
struct SDL_Window;
|
||||||
|
|
||||||
|
namespace aurora::utils {
|
||||||
|
|
||||||
|
class BackendBinding {
|
||||||
|
public:
|
||||||
|
virtual ~BackendBinding() = default;
|
||||||
|
|
||||||
|
virtual uint64_t GetSwapChainImplementation() = 0;
|
||||||
|
virtual WGPUTextureFormat GetPreferredSwapChainTextureFormat() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
BackendBinding(SDL_Window* window, WGPUDevice device);
|
||||||
|
|
||||||
|
SDL_Window* m_window = nullptr;
|
||||||
|
WGPUDevice m_device = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
void DiscoverAdapter(dawn::native::Instance* instance, SDL_Window* window, wgpu::BackendType type);
|
||||||
|
BackendBinding* CreateBinding(wgpu::BackendType type, SDL_Window* window, WGPUDevice device);
|
||||||
|
|
||||||
|
} // namespace aurora::utils
|
|
@ -0,0 +1,108 @@
|
||||||
|
#include "BackendBinding.hpp"
|
||||||
|
|
||||||
|
#include <SDL_metal.h>
|
||||||
|
#include <dawn/native/MetalBackend.h>
|
||||||
|
|
||||||
|
#import <QuartzCore/CAMetalLayer.h>
|
||||||
|
|
||||||
|
template <typename T> DawnSwapChainImplementation CreateSwapChainImplementation(T *swapChain) {
|
||||||
|
DawnSwapChainImplementation impl = {};
|
||||||
|
impl.userData = swapChain;
|
||||||
|
impl.Init = [](void *userData, void *wsiContext) {
|
||||||
|
auto *ctx = static_cast<typename T::WSIContext *>(wsiContext);
|
||||||
|
reinterpret_cast<T *>(userData)->Init(ctx);
|
||||||
|
};
|
||||||
|
impl.Destroy = [](void *userData) { delete reinterpret_cast<T *>(userData); };
|
||||||
|
impl.Configure = [](void *userData, WGPUTextureFormat format, WGPUTextureUsage allowedUsage, uint32_t width,
|
||||||
|
uint32_t height) {
|
||||||
|
return static_cast<T *>(userData)->Configure(format, allowedUsage, width, height);
|
||||||
|
};
|
||||||
|
impl.GetNextTexture = [](void *userData, DawnSwapChainNextTexture *nextTexture) {
|
||||||
|
return static_cast<T *>(userData)->GetNextTexture(nextTexture);
|
||||||
|
};
|
||||||
|
impl.Present = [](void *userData) { return static_cast<T *>(userData)->Present(); };
|
||||||
|
return impl;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace aurora::utils {
|
||||||
|
class SwapChainImplMTL {
|
||||||
|
public:
|
||||||
|
using WSIContext = DawnWSIContextMetal;
|
||||||
|
|
||||||
|
explicit SwapChainImplMTL(SDL_Window *window) : m_view(SDL_Metal_CreateView(window)) {}
|
||||||
|
|
||||||
|
~SwapChainImplMTL() { SDL_Metal_DestroyView(m_view); }
|
||||||
|
|
||||||
|
void Init(DawnWSIContextMetal *ctx) {
|
||||||
|
mMtlDevice = ctx->device;
|
||||||
|
mCommandQueue = ctx->queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
DawnSwapChainError Configure(WGPUTextureFormat format, WGPUTextureUsage usage, uint32_t width, uint32_t height) {
|
||||||
|
if (format != WGPUTextureFormat_BGRA8Unorm) {
|
||||||
|
return "unsupported format";
|
||||||
|
}
|
||||||
|
assert(width > 0);
|
||||||
|
assert(height > 0);
|
||||||
|
|
||||||
|
CGSize size = {};
|
||||||
|
size.width = width;
|
||||||
|
size.height = height;
|
||||||
|
|
||||||
|
mLayer = (__bridge CAMetalLayer *)(SDL_Metal_GetLayer(m_view));
|
||||||
|
[mLayer setDevice:mMtlDevice];
|
||||||
|
[mLayer setPixelFormat:MTLPixelFormatBGRA8Unorm];
|
||||||
|
[mLayer setDrawableSize:size];
|
||||||
|
|
||||||
|
constexpr uint32_t kFramebufferOnlyTextureUsages = WGPUTextureUsage_RenderAttachment | WGPUTextureUsage_Present;
|
||||||
|
bool hasOnlyFramebufferUsages = (usage & (~kFramebufferOnlyTextureUsages)) == 0u;
|
||||||
|
if (hasOnlyFramebufferUsages) {
|
||||||
|
[mLayer setFramebufferOnly:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
return DAWN_SWAP_CHAIN_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
DawnSwapChainError GetNextTexture(DawnSwapChainNextTexture *nextTexture) {
|
||||||
|
mCurrentDrawable = [mLayer nextDrawable];
|
||||||
|
mCurrentTexture = mCurrentDrawable.texture;
|
||||||
|
nextTexture->texture.ptr = (__bridge void *)(mCurrentTexture);
|
||||||
|
return DAWN_SWAP_CHAIN_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
DawnSwapChainError Present() {
|
||||||
|
id<MTLCommandBuffer> commandBuffer = [mCommandQueue commandBuffer];
|
||||||
|
[commandBuffer presentDrawable:mCurrentDrawable];
|
||||||
|
[commandBuffer commit];
|
||||||
|
return DAWN_SWAP_CHAIN_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
SDL_MetalView m_view = nil;
|
||||||
|
id<MTLDevice> mMtlDevice = nil;
|
||||||
|
id<MTLCommandQueue> mCommandQueue = nil;
|
||||||
|
|
||||||
|
CAMetalLayer *mLayer = nullptr;
|
||||||
|
id<CAMetalDrawable> mCurrentDrawable = nil;
|
||||||
|
id<MTLTexture> mCurrentTexture = nil;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MetalBinding : public BackendBinding {
|
||||||
|
public:
|
||||||
|
MetalBinding(SDL_Window *window, WGPUDevice device) : BackendBinding(window, device) {}
|
||||||
|
|
||||||
|
uint64_t GetSwapChainImplementation() override {
|
||||||
|
if (m_swapChainImpl.userData == nullptr) {
|
||||||
|
m_swapChainImpl = CreateSwapChainImplementation(new SwapChainImplMTL(m_window));
|
||||||
|
}
|
||||||
|
return reinterpret_cast<uint64_t>(&m_swapChainImpl);
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUTextureFormat GetPreferredSwapChainTextureFormat() override { return WGPUTextureFormat_BGRA8Unorm; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
DawnSwapChainImplementation m_swapChainImpl{};
|
||||||
|
};
|
||||||
|
|
||||||
|
BackendBinding *CreateMetalBinding(SDL_Window *window, WGPUDevice device) { return new MetalBinding(window, device); }
|
||||||
|
} // namespace aurora::utils
|
|
@ -0,0 +1,28 @@
|
||||||
|
#include "BackendBinding.hpp"
|
||||||
|
|
||||||
|
#include <SDL_video.h>
|
||||||
|
#include <dawn/native/OpenGLBackend.h>
|
||||||
|
|
||||||
|
namespace aurora::utils {
|
||||||
|
class OpenGLBinding : public BackendBinding {
|
||||||
|
public:
|
||||||
|
OpenGLBinding(SDL_Window* window, WGPUDevice device) : BackendBinding(window, device) {}
|
||||||
|
|
||||||
|
uint64_t GetSwapChainImplementation() override {
|
||||||
|
if (m_swapChainImpl.userData == nullptr) {
|
||||||
|
m_swapChainImpl = dawn::native::opengl::CreateNativeSwapChainImpl(
|
||||||
|
m_device, [](void* userdata) { SDL_GL_SwapWindow(static_cast<SDL_Window*>(userdata)); }, m_window);
|
||||||
|
}
|
||||||
|
return reinterpret_cast<uint64_t>(&m_swapChainImpl);
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUTextureFormat GetPreferredSwapChainTextureFormat() override {
|
||||||
|
return dawn::native::opengl::GetNativeSwapChainPreferredFormat(&m_swapChainImpl);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DawnSwapChainImplementation m_swapChainImpl{};
|
||||||
|
};
|
||||||
|
|
||||||
|
BackendBinding* CreateOpenGLBinding(SDL_Window* window, WGPUDevice device) { return new OpenGLBinding(window, device); }
|
||||||
|
} // namespace aurora::utils
|
|
@ -0,0 +1,33 @@
|
||||||
|
#include "BackendBinding.hpp"
|
||||||
|
|
||||||
|
#include <SDL_vulkan.h>
|
||||||
|
#include <cassert>
|
||||||
|
#include <dawn/native/VulkanBackend.h>
|
||||||
|
|
||||||
|
namespace aurora::utils {
|
||||||
|
class VulkanBinding : public BackendBinding {
|
||||||
|
public:
|
||||||
|
VulkanBinding(SDL_Window* window, WGPUDevice device) : BackendBinding(window, device) {}
|
||||||
|
|
||||||
|
uint64_t GetSwapChainImplementation() override {
|
||||||
|
if (m_swapChainImpl.userData == nullptr) {
|
||||||
|
VkSurfaceKHR surface = VK_NULL_HANDLE;
|
||||||
|
if (SDL_Vulkan_CreateSurface(m_window, dawn::native::vulkan::GetInstance(m_device), &surface) != SDL_TRUE) {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
m_swapChainImpl = dawn::native::vulkan::CreateNativeSwapChainImpl(m_device, surface);
|
||||||
|
}
|
||||||
|
return reinterpret_cast<uint64_t>(&m_swapChainImpl);
|
||||||
|
}
|
||||||
|
|
||||||
|
WGPUTextureFormat GetPreferredSwapChainTextureFormat() override {
|
||||||
|
assert(m_swapChainImpl.userData != nullptr);
|
||||||
|
return dawn::native::vulkan::GetNativeSwapChainPreferredFormat(&m_swapChainImpl);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DawnSwapChainImplementation m_swapChainImpl{};
|
||||||
|
};
|
||||||
|
|
||||||
|
BackendBinding* CreateVulkanBinding(SDL_Window* window, WGPUDevice device) { return new VulkanBinding(window, device); }
|
||||||
|
} // namespace aurora::utils
|
Loading…
Reference in New Issue