Some initial implementation.
This commit is contained in:
parent
a8813349a1
commit
31af297bab
2
external/scons-plus-plus
vendored
2
external/scons-plus-plus
vendored
@ -1 +1 @@
|
||||
Subproject commit bdf063a16c6bafd137f57eee780c83345887c46c
|
||||
Subproject commit 941f94a7b6ad9242ee1404663dfd855dcf203817
|
@ -11,8 +11,11 @@ prog_app = env.UnityProgram(
|
||||
dependencies = {
|
||||
'mijin': {},
|
||||
'SDL': {
|
||||
|
||||
}
|
||||
'options': {
|
||||
'ref': '76ce83801ade3ac922ad5ba6fddc49764c24206a'
|
||||
}
|
||||
},
|
||||
'spdlog': {}
|
||||
}
|
||||
)
|
||||
env.Default(prog_app)
|
||||
|
@ -1,5 +1,49 @@
|
||||
|
||||
#include <mijin/util/scope_guard.hpp>
|
||||
#include <mijin/util/variant.hpp>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include "./sdlpp/event.hpp"
|
||||
#include "./sdlpp/gpu.hpp"
|
||||
#include "./sdlpp/window.hpp"
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
return 0;
|
||||
if (SDL_Init(0) != SDL_TRUE)
|
||||
{
|
||||
spdlog::error("Error initializing SDL.");
|
||||
return 1;
|
||||
}
|
||||
MIJIN_SCOPE_EXIT {
|
||||
SDL_Quit();
|
||||
};
|
||||
|
||||
sdlpp::Window window;
|
||||
window.create({
|
||||
.flags = {.vulkan = true}
|
||||
});
|
||||
|
||||
sdlpp::GPUDevice gpuDevice;
|
||||
gpuDevice.create({.formatFlags{.spirv = true}});
|
||||
|
||||
gpuDevice.claimWindow(window);
|
||||
|
||||
const SDL_GPUTextureFormat texForm = SDL_GetGPUSwapchainTextureFormat(gpuDevice, window);
|
||||
(void) texForm;
|
||||
|
||||
bool running = true;
|
||||
while(running)
|
||||
{
|
||||
std::optional<sdlpp::sdl_event_t> event;
|
||||
while ((event = sdlpp::pollEvent()).has_value())
|
||||
{
|
||||
std::visit(mijin::Visitor{
|
||||
[&](const sdlpp::QuitEvent&) { running = false; },
|
||||
[](const auto&) {} // default handler
|
||||
}, *event);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
54
private/sdl_gpu_test/sdlpp/common.hpp
Normal file
54
private/sdl_gpu_test/sdlpp/common.hpp
Normal file
@ -0,0 +1,54 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_COMMON_HPP_INCLUDED)
|
||||
#define SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_COMMON_HPP_INCLUDED 1
|
||||
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
#include <mijin/debug/assert.hpp>
|
||||
#include <mijin/util/bitflags.hpp>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
namespace sdlpp
|
||||
{
|
||||
template<typename THandle, typename TConcrete>
|
||||
class Base
|
||||
{
|
||||
protected:
|
||||
THandle* mHandle = nullptr;
|
||||
protected:
|
||||
Base() noexcept = default;
|
||||
explicit Base(THandle* handle) noexcept : mHandle(handle) {}
|
||||
Base(Base&& other) noexcept : mHandle(std::exchange(other.mHandle, nullptr)) {}
|
||||
|
||||
Base& operator=(Base&& other) noexcept
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
static_cast<TConcrete&>(*this).destroy();
|
||||
mHandle = std::exchange(other.mHandle, nullptr);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
public:
|
||||
Base(const Base&) = delete;
|
||||
~Base() noexcept
|
||||
{
|
||||
static_cast<TConcrete&>(*this).destroy();
|
||||
}
|
||||
Base& operator=(const Base&) = delete;
|
||||
auto operator<=>(const Base& other) const noexcept = default;
|
||||
|
||||
operator THandle*() const noexcept { return mHandle; }
|
||||
};
|
||||
|
||||
class SDLError : std::runtime_error
|
||||
{
|
||||
public:
|
||||
SDLError() : std::runtime_error(SDL_GetError()) {}
|
||||
};
|
||||
} // namespace sdlpp
|
||||
|
||||
#endif // !defined(SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_COMMON_HPP_INCLUDED)
|
52
private/sdl_gpu_test/sdlpp/event.hpp
Normal file
52
private/sdl_gpu_test/sdlpp/event.hpp
Normal file
@ -0,0 +1,52 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_EVENT_HPP_INCLUDED)
|
||||
#define SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_EVENT_HPP_INCLUDED 1
|
||||
|
||||
#include <optional>
|
||||
#include <variant>
|
||||
|
||||
namespace sdlpp
|
||||
{
|
||||
struct Event
|
||||
{
|
||||
Uint64 timestamp;
|
||||
|
||||
template<typename TBase>
|
||||
explicit Event(const TBase& base) noexcept : timestamp(base.timestamp) {}
|
||||
};
|
||||
struct QuitEvent : Event
|
||||
{
|
||||
explicit QuitEvent(const SDL_QuitEvent& base) noexcept : Event(base) {}
|
||||
};
|
||||
struct WindowEvent : Event
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
using sdl_event_t = std::variant<
|
||||
WindowEvent,
|
||||
QuitEvent
|
||||
>;
|
||||
|
||||
[[nodiscard]]
|
||||
std::optional<sdl_event_t> pollEvent() noexcept
|
||||
{
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event))
|
||||
{
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_EVENT_QUIT:
|
||||
return QuitEvent(event.quit);
|
||||
default:
|
||||
// can't translate this yet
|
||||
break;
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
} // namespace sdlpp
|
||||
|
||||
#endif // !defined(SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_EVENT_HPP_INCLUDED)
|
79
private/sdl_gpu_test/sdlpp/gpu.hpp
Normal file
79
private/sdl_gpu_test/sdlpp/gpu.hpp
Normal file
@ -0,0 +1,79 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_GPU_HPP_INCLUDED)
|
||||
#define SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_GPU_HPP_INCLUDED 1
|
||||
|
||||
#include <SDL3/SDL_gpu.h>
|
||||
|
||||
#include "./common.hpp"
|
||||
|
||||
namespace sdlpp
|
||||
{
|
||||
struct GpuShaderFormat : mijin::BitFlags<GpuShaderFormat>
|
||||
{
|
||||
bool private_ : 1 = false;
|
||||
bool spirv : 1 = false;
|
||||
bool dxbc : 1 = false;
|
||||
bool dxil : 1 = false;
|
||||
bool msl : 1 = false;
|
||||
bool metallib : 1 = false;
|
||||
|
||||
constexpr operator SDL_GPUShaderFormat() const noexcept
|
||||
{
|
||||
return std::bit_cast<std::uint8_t>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
struct GPUDeviceCreateArgs
|
||||
{
|
||||
GpuShaderFormat formatFlags = {};
|
||||
bool debugMode = false;
|
||||
const char* name = nullptr;
|
||||
};
|
||||
|
||||
class GPUDevice : public Base<SDL_GPUDevice, GPUDevice>
|
||||
{
|
||||
public:
|
||||
GPUDevice() noexcept = default;
|
||||
GPUDevice(const GPUDevice&) = delete;
|
||||
GPUDevice(GPUDevice&& other) noexcept : Base(std::move(other)) {}
|
||||
|
||||
GPUDevice& operator=(const GPUDevice&) = delete;
|
||||
GPUDevice& operator=(GPUDevice&& other) noexcept
|
||||
{
|
||||
Base::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
auto operator<=>(const GPUDevice& other) const noexcept = default;
|
||||
|
||||
void create(const GPUDeviceCreateArgs& args = {})
|
||||
{
|
||||
MIJIN_ASSERT(mHandle == nullptr, "GPUDevice has already been created.");
|
||||
mHandle = SDL_CreateGPUDevice(args.formatFlags, args.debugMode, args.name);
|
||||
if (mHandle == nullptr)
|
||||
{
|
||||
throw SDLError();
|
||||
}
|
||||
}
|
||||
|
||||
void destroy() noexcept
|
||||
{
|
||||
if (mHandle != nullptr)
|
||||
{
|
||||
SDL_DestroyGPUDevice(mHandle);
|
||||
mHandle = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void claimWindow(SDL_Window* window) const
|
||||
{
|
||||
if (!SDL_ClaimWindowForGPUDevice(*this, window))
|
||||
{
|
||||
throw SDLError();
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace sdlpp
|
||||
|
||||
#endif // !defined(SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_GPU_HPP_INCLUDED)
|
96
private/sdl_gpu_test/sdlpp/window.hpp
Normal file
96
private/sdl_gpu_test/sdlpp/window.hpp
Normal file
@ -0,0 +1,96 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_WINDOW_HPP_INCLUDED)
|
||||
#define SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_WINDOW_HPP_INCLUDED 1
|
||||
|
||||
#include "./common.hpp"
|
||||
|
||||
namespace sdlpp
|
||||
{
|
||||
struct WindowFlags : mijin::BitFlags<WindowFlags>
|
||||
{
|
||||
bool fullscreen : 1; // 0x0000000000000001 /**< window is in fullscreen mode */
|
||||
bool opengl : 1; // 0x0000000000000002 /**< window usable with OpenGL context */
|
||||
bool occluded : 1; // 0x0000000000000004 /**< window is occluded */
|
||||
bool hidden : 1; // 0x0000000000000008) /**< window is neither mapped onto the desktop nor shown in the taskbar/dock/window list; SDL_ShowWindow( is required for it to become visible */
|
||||
bool borderless : 1; // 0x0000000000000010 /**< no window decoration */
|
||||
bool resizable : 1; // 0x0000000000000020 /**< window can be resized */
|
||||
bool minimized : 1; // 0x0000000000000040 /**< window is minimized */
|
||||
bool maximized : 1; // 0x0000000000000080 /**< window is maximized */
|
||||
bool mouse_grabbed : 1; // 0x0000000000000100 /**< window has grabbed mouse input */
|
||||
bool input_focus : 1; // 0x0000000000000200 /**< window has input focus */
|
||||
bool mouse_focus : 1; // 0x0000000000000400 /**< window has mouse focus */
|
||||
bool external : 1; // 0x0000000000000800 /**< window not created by SDL */
|
||||
bool modal : 1; // 0x0000000000001000 /**< window is modal */
|
||||
bool high_pixel_density : 1; // 0x0000000000002000 /**< window uses high pixel density back buffer if possible */
|
||||
bool mouse_capture : 1; // 0x0000000000004000) /**< window has mouse captured (unrelated to MOUSE_GRABBED */
|
||||
bool mouse_relative_mode : 1; // 0x0000000000008000 /**< window has relative mode enabled */
|
||||
bool always_on_top : 1; // 0x0000000000010000 /**< window should always be above others */
|
||||
bool utility : 1; // 0x0000000000020000 /**< window should be treated as a utility window, not showing in the task bar and window list */
|
||||
bool tooltip : 1; // 0x0000000000040000 /**< window should be treated as a tooltip and does not get mouse or keyboard focus, requires a parent window */
|
||||
bool popup_menu : 1; // 0x0000000000080000 /**< window should be treated as a popup menu, requires a parent window */
|
||||
bool keyboard_grabbed : 1; // 0x0000000000100000 /**< window has grabbed keyboard input */
|
||||
bool unused0 : 1; // 0x0000000000200000
|
||||
bool unused1 : 1; // 0x0000000000400000
|
||||
bool unused2 : 1; // 0x0000000000800000
|
||||
bool unused3 : 1; // 0x0000000001000000
|
||||
bool unused4 : 1; // 0x0000000002000000
|
||||
bool unused5 : 1; // 0x0000000004000000
|
||||
bool unused6 : 1; // 0x0000000008000000
|
||||
bool vulkan : 1; // 0x0000000010000000 /**< window usable for Vulkan surface */
|
||||
bool metal : 1; // 0x0000000020000000 /**< window usable for Metal view */
|
||||
bool transparent : 1; // 0x0000000040000000 /**< window with transparent buffer */
|
||||
bool notFocusable : 1; // 0x0000000080000000 /**< window should not be focusable */
|
||||
|
||||
constexpr operator SDL_WindowFlags () const noexcept
|
||||
{
|
||||
return std::bit_cast<std::uint32_t>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
struct WindowCreateArgs
|
||||
{
|
||||
const char* title = "Window";
|
||||
int width = 1280;
|
||||
int height = 720;
|
||||
WindowFlags flags = {};
|
||||
};
|
||||
|
||||
class Window : public Base<SDL_Window, Window>
|
||||
{
|
||||
public:
|
||||
Window() noexcept = default;
|
||||
Window(const Window&) = delete;
|
||||
Window(Window&& other) noexcept : Base(std::move(other)) {}
|
||||
|
||||
Window& operator=(const Window&) = delete;
|
||||
Window& operator=(Window&& other) noexcept
|
||||
{
|
||||
Base::operator=(std::move(other));
|
||||
return *this;
|
||||
}
|
||||
auto operator<=>(const Window& other) const noexcept = default;
|
||||
|
||||
void create(const WindowCreateArgs& args = {})
|
||||
{
|
||||
MIJIN_ASSERT(mHandle == nullptr, "Window has already been created.");
|
||||
mHandle = SDL_CreateWindow(args.title, args.width, args.height, args.flags);
|
||||
if (mHandle == nullptr)
|
||||
{
|
||||
throw SDLError();
|
||||
}
|
||||
}
|
||||
|
||||
void destroy() noexcept
|
||||
{
|
||||
if (mHandle != nullptr)
|
||||
{
|
||||
SDL_DestroyWindow(mHandle);
|
||||
mHandle = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace sdlpp
|
||||
|
||||
#endif // !defined(SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SDLPP_WINDOW_HPP_INCLUDED)
|
Loading…
x
Reference in New Issue
Block a user