Wayland: initialize surface and render to video

This commit is contained in:
Matteo De Carlo
2024-12-24 18:18:50 +01:00
parent 30bb9e10d5
commit 54f7f1dc53
20 changed files with 1236 additions and 74 deletions
+1
View File
@@ -22,6 +22,7 @@ include(CMakeDependentOption)
if(UNIX)
option(WICKED_LINUX_TEMPLATE "Build WickedEngine Linux template" ON)
option(WAYLAND_BACKEND "Build WickedEngine Wayland backend" ON)
elseif(WIN32)
option(WICKED_WINDOWS_TEMPLATE "Build WickedEngine Windows template" ON)
endif()
+2 -1
View File
@@ -132,7 +132,8 @@ void Example_ImGui::Initialize()
#ifdef _WIN32
ImGui_ImplWin32_Init(window);
#elif defined(SDL2)
ImGui_ImplSDL2_InitForVulkan(window);
IM_ASSERT(window.type == wi::platform::LinuxWindow::eSDLWindow);
ImGui_ImplSDL2_InitForVulkan(window.sdl_window);
#endif
IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");
@@ -23,10 +23,10 @@
#endif
#include "../WickedEngine/wiProfiler.h"
#include "../WickedEngine/wiBacklog.h"
#include "../WickedEngine/wiPrimitive.h"
#include "../WickedEngine/wiRenderPath3D.h"
#include "wiProfiler.h"
#include "wiBacklog.h"
#include "wiPrimitive.h"
#include "wiRenderPath3D.h"
#include "../Editor/ModelImporter.h"
#include <fstream>
@@ -174,7 +174,8 @@ void Example_ImGui::Initialize()
hWnd = window;
ImGui_ImplWin32_Init(window);
#elif defined(SDL2)
ImGui_ImplSDL2_InitForVulkan(window);
IM_ASSERT(window.type == wi::platform::LinuxWindow::eSDLWindow);
ImGui_ImplSDL2_InitForVulkan(window.sdl_window);
#endif
IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");
@@ -457,7 +458,7 @@ void Example_ImGuiRenderer::Update(float dt)
ImGui_Impl_CreateDeviceObjects();
}
#ifdef _WIN32
ImGui_ImplWin32_NewFrame();
#elif defined(SDL2)
@@ -681,7 +682,7 @@ void Example_ImGuiRenderer::Update(float dt)
bool bUseChild = false;
if (use_fixed_height > 0) bUseChild = true;
if(bUseChild) ImGui::BeginChild("##objectsc", ImVec2(0.0f, use_fixed_height), false, ImGuiWindowFlags_None); //ImGuiWindowFlags_AlwaysVerticalScrollbar
for (int i = 0; i < size; i++)
{
Entity e = scene.objects.GetEntity(i);
@@ -1029,7 +1030,7 @@ void Example_ImGuiRenderer::Update(float dt)
ImGui::EndTabBar();
}
}
if (ImGui::CollapsingHeader(ICON_MD_SETTINGS " Settings", ImGuiTreeNodeFlags_None)) //ImGuiTreeNodeFlags_DefaultOpen
{
ImGui::SetCursorPos(ImGui::GetCursorPos() + ImVec2(0.0f, 3.0f));
@@ -1390,7 +1391,7 @@ void Example_ImGuiRenderer::Update(float dt)
if (ImGui::Selectable(lua_history[i].c_str(), is_selected)) {
#ifdef _WIN32
strcpy_s(lua, lua_history[i].c_str());
#elif __linux__
#elif __linux__
strcpy(lua, lua_history[i].c_str());
#endif
bSetKeyBoardFocus = true;
@@ -1489,7 +1490,7 @@ void Example_ImGuiRenderer::Update(float dt)
}
float movespeed = CAMERAMOVESPEED;
if (imgui_io.KeyShift)
{
movespeed *= 3.0; //Speed up camera.
+46 -1
View File
@@ -3,6 +3,9 @@
#include "stdafx.h"
#include "sdl2.h"
#include "Wayland/wiWaylandBackend.h"
#include "Wayland/wiWaylandWindow.h"
#include <wiPlatform.h>
int sdl_loop(Tests &tests)
{
@@ -61,7 +64,7 @@ int sdl_loop(Tests &tests)
return 0;
}
int main(int argc, char *argv[])
int main_sdl2(int argc, char *argv[])
{
Tests tests;
// TODO: Place code here.
@@ -89,3 +92,45 @@ int main(int argc, char *argv[])
SDL_Quit();
return ret;
}
void wayland_loop(wi::wayland::Backend &wwbackend, Tests &tests)
{
bool quit = false;
wwbackend.window.on_close = [&quit](wi::wayland::Window*w) { quit = false; };
while(!quit)
{
tests.Run();
if (wwbackend.dispatch() < 0)
break;
if (wwbackend.window.AcceptDesiredDimensions())
tests.SetWindow(&wwbackend.window);
}
}
bool main_wayland(int argc, char *argv[])
{
wi::wayland::Backend wwbackend;
if (!wwbackend.Init())
return false;
if (!wwbackend.CreateWindow("Wicked Engine Tests"))
return false;
Tests tests;
tests.SetWindow(&wwbackend.window);
wayland_loop(wwbackend, tests);
wwbackend.window.Deinit();
wwbackend.DeInit();
return true;
}
int main(int argc, char *argv[])
{
// Attempt to initialize wayland backend
if (!main_wayland(argc, argv))
main_sdl2(argc, argv);
}
+19
View File
@@ -0,0 +1,19 @@
[Buildset]
BuildItems=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x01\x00\x00\x00\x0b\x00\x00\x00\x00\x01\x00\x00\x00\x18\x00W\x00i\x00c\x00k\x00e\x00d\x00E\x00n\x00g\x00i\x00n\x00e)
[CMake]
Build Directory Count=1
Current Build Directory Index-Host System=0
[CMake][CMake Build Directory 0]
Build Directory Path=/home/matteo/projects/WickedEngine/WickedEngine/cmake-build-debug
Build Type=Debug
CMake Binary=/usr/bin/cmake
CMake Executable=/usr/bin/cmake
Environment Profile=
Extra Arguments=
Install Directory=/usr/local
Runtime=Host System
[Project]
VersionControlSupport=kdevgit
+76 -5
View File
@@ -47,6 +47,54 @@ else ()
if((${SDL_VERSION_MAJOR} GREATER_EQUAL 2) AND (${SDL2_VERSION_MINOR} GREATER_EQUAL 0) AND (${SDL2_VERSION_PATCH} GREATER_EQUAL 14))
add_compile_definitions(SDL2_FEATURE_CONTROLLER_LED=1)
endif()
if (WAYLAND_BACKEND)
find_package(PkgConfig REQUIRED)
pkg_check_modules(WAYLAND_CLIENT REQUIRED wayland-client)
pkg_check_modules(WAYLAND_SCANNER REQUIRED wayland-scanner)
pkg_check_modules(WAYLAND_PROTOCOLS REQUIRED wayland-protocols)
# Get variables
pkg_get_variable(WAYLAND_SCANNER_BIN wayland-scanner wayland_scanner)
pkg_get_variable(WAYLAND_PROTOCOLS_DATADIR wayland-protocols pkgdatadir)
################################################################################################################
# Wayland protocol generated code
function(GENERATE_XDG_PROTOCOLS)
# GENERATE XDG PROTOCOLS SOURCES
set(XDG_PROTOCOLS_SOURCES)
set(XDG_PROTOCOLS_HEADERS)
foreach(XML ${ARGN})
get_filename_component(XML_NAME "${XML}" NAME_WE)
MESSAGE("Generating C source code for ${XML} -> ${XML_NAME}")
add_custom_command(COMMAND ${WAYLAND_SCANNER_BIN}
ARGS private-code "${XML}" "${CMAKE_CURRENT_BINARY_DIR}/${XML_NAME}.c"
DEPENDS "${XML}"
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${XML_NAME}.c"
COMMENT "Generating \"${XML_NAME}\" protocol private code."
)
list(APPEND XDG_PROTOCOLS_SOURCES "${CMAKE_CURRENT_BINARY_DIR}/${XML_NAME}.c")
add_custom_command(COMMAND ${WAYLAND_SCANNER_BIN}
ARGS client-header "${XML}" "${CMAKE_CURRENT_BINARY_DIR}/${XML_NAME}.h"
DEPENDS "${XML}"
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${XML_NAME}.h"
COMMENT "Generating \"${XML_NAME}\" protocol header."
)
list(APPEND XDG_PROTOCOLS_HEADERS "${CMAKE_CURRENT_BINARY_DIR}/${XML_NAME}.h")
set(XDG_PROTOCOLS_SOURCES ${XDG_PROTOCOLS_SOURCES} PARENT_SCOPE)
set(XDG_PROTOCOLS_HEADERS ${XDG_PROTOCOLS_HEADERS} PARENT_SCOPE)
endforeach()
endfunction()
GENERATE_XDG_PROTOCOLS(
"${WAYLAND_PROTOCOLS_DATADIR}/stable/xdg-shell/xdg-shell.xml"
"${WAYLAND_PROTOCOLS_DATADIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml"
)
file(GLOB WAYLAND_SOURCES CONFIGURE_DEPENDS Wayland/*.cpp)
file(GLOB WAYLAND_HEADERS CONFIGURE_DEPENDS Wayland/*.h)
set(WAYLAND_SOURCES ${WAYLAND_SOURCES} ${XDG_PROTOCOLS_SOURCES})
set(WAYLAND_HEADERS ${WAYLAND_HEADERS} ${XDG_PROTOCOLS_HEADERS})
endif()
endif()
add_subdirectory(LUA)
@@ -64,6 +112,8 @@ list(REMOVE_ITEM SOURCE_FILES offlineshadercompiler.cpp)
add_library(${TARGET_NAME} ${WICKED_LIBRARY_TYPE}
${SOURCE_FILES}
${HEADER_FILES}
${WAYLAND_SOURCES}
${WAYLAND_HEADERS}
)
if(MSVC)
@@ -71,7 +121,7 @@ if(MSVC)
endif()
add_library(WickedEngine ALIAS ${TARGET_NAME})
set_target_properties(${TARGET_NAME} PROPERTIES PUBLIC_HEADER "${HEADER_FILES}")
set_target_properties(${TARGET_NAME} PROPERTIES PUBLIC_HEADER "${HEADER_FILES} ${WAYLAND_HEADERS}")
target_include_directories(${TARGET_NAME} SYSTEM PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
@@ -106,12 +156,15 @@ else ()
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
target_compile_options(${TARGET_NAME} PRIVATE
# C and C++ warnings
-Wuninitialized
#-Wwrite-strings
#-Winit-self
#-Wreturn-type
#-Wreorder
#-Werror=delete-non-virtual-dtor
# C++ only warnings
#$<$<COMPILE_LANGUAGE:CXX>:-Wreorder>
#$<$<COMPILE_LANGUAGE:CXX>:-Werror=delete-non-virtual-dtor>
# Treat warnings as errors
#-Werror
#uncomment this to stop the compilation at the first error
# -Wfatal-errors
@@ -120,19 +173,37 @@ else ()
# add some warnings and set them as errors
# read more details here: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
target_compile_options(${TARGET_NAME} PRIVATE
# C and C++ warnings
-Wuninitialized
-Wmaybe-uninitialized
-Wwrite-strings
-Winit-self
-Wreturn-type
-Wreorder
-Werror=delete-non-virtual-dtor
# C++ only warnings
$<$<COMPILE_LANGUAGE:CXX>:-Wreorder>
$<$<COMPILE_LANGUAGE:CXX>:-Werror=delete-non-virtual-dtor>
# Treat warnings as errors
-Werror
#uncomment this to stop the compilation at the first error
# -Wfatal-errors
)
endif()
if (WAYLAND_BACKEND)
target_include_directories(${TARGET_NAME}
PUBLIC ${WAYLAND_CLIENT_INCLUDE_DIRS}
# PRIVATE ${WAYLAND_CURSOR_INCLUDE_DIRS}
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
# PUBLIC $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/WickedEngine>
)
target_link_libraries(${TARGET_NAME}
PUBLIC ${WAYLAND_CLIENT_LIBRARIES}
# PRIVATE ${WAYLAND_CURSOR_LIBRARIES}
)
endif()
target_link_libraries(${TARGET_NAME} PRIVATE dl)
set(LIBDXCOMPILER "libdxcompiler.so")
+141
View File
@@ -0,0 +1,141 @@
#include "wiWaylandBackend.h"
#include "wiWaylandUtils.h"
#include <wayland/wayland-client-core.h>
#include <wayland/wayland-client-protocol.h>
#include <wayland/wayland-client.h>
#include <iostream>
#include "xdg-shell.h"
#include "xdg-decoration-unstable-v1.h"
using namespace wi::wayland;
/// functions callbacks - START
extern "C" void registry_global(void *data, wl_registry *raw_registry, uint32_t id, const char* interface, uint32_t version)
{
Backend *backend = static_cast<Backend*>(data);
backend->registry_event_add(id, interface, version);
}
extern "C" void registry_global_remove(void *data, wl_registry *raw_registry, uint32_t id)
{
Backend *backend = static_cast<Backend*>(data);
backend->registry_event_remove(id);
}
extern "C" void window_manager_pong(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial)
{
Backend *backend = static_cast<Backend*>(data);
backend->window_manager_pong(serial);
}
/// functions callbacks - END
bool Backend::Init()
{
const char* name = nullptr;
display = wl_display_connect(name);
if (display == nullptr) {std::cerr<<"wl_display_connect failed"<<std::endl; return false;}
registry = wl_display_get_registry(display);
if (registry == nullptr) {std::cerr<<"wl_display_get_registry failed"<<std::endl; return false;}
if (!init_registry()) {std::cerr<<"init registry failed"<<std::endl; return false;}
if (!bind_compositor()) {std::cerr<<"bind compositor failed"<<std::endl; return false;}
if (!registry_has("xdg_wm_base")) {std::cerr<<"XDG WM BASE not found"<<std::endl; return false;}
if (!bind_xdg_wm_base()) {std::cerr<<"bind xdg_wm_base failed"<<std::endl; return false;}
if (!init_window_manager()) {std::cerr<<"xdg_wm_base init failed"<<std::endl; return false;}
if (!bind_decoration_manager()) {std::cerr<<"bind decoration_manager failed"<<std::endl;} //optional, being "unstable" API
return true;
}
bool Backend::init_registry()
{
registry_listener.global = &::registry_global;
registry_listener.global_remove = &::registry_global_remove;
wl_registry_add_listener(registry, &this->registry_listener, this);
dispatch();
roundtrip();
return true;
}
bool Backend::registry_has(const char* interface_name) const
{
return registry_map.find(interface_name) != registry_map.end();
}
bool Backend::bind_compositor()
{
compositor = bind<wl_compositor>("wl_compositor", &wl_compositor_interface);
return compositor != nullptr;
}
bool Backend::bind_xdg_wm_base()
{
window_manager = this->bind<xdg_wm_base>("xdg_wm_base", &xdg_wm_base_interface);
return window_manager != nullptr;
}
bool Backend::bind_decoration_manager()
{
decoration_manager = this->bind<zxdg_decoration_manager_v1>(
"zxdg_decoration_manager_v1", &zxdg_decoration_manager_v1_interface);
return window_manager != nullptr;
}
bool Backend::init_window_manager()
{
window_manager_listener.ping = &::window_manager_pong;
xdg_wm_base_add_listener(window_manager, &window_manager_listener, this);
return true;
}
void Backend::DeInit()
{
safe_delete(decoration_manager, zxdg_decoration_manager_v1_destroy);
safe_delete(window_manager, xdg_wm_base_destroy);
safe_delete(compositor, wl_compositor_destroy);
// registry needs to be killed before, otherwhise the application will crash
safe_delete(registry, wl_registry_destroy);
safe_delete(display, wl_display_disconnect);
}
bool Backend::CreateWindow(const char* title)
{
return window.Init(this, title);
}
int Backend::dispatch()
{
return wl_display_dispatch(display);
}
int Backend::roundtrip()
{
return wl_display_roundtrip(display);
}
void Backend::registry_event_add(uint32_t id, const char* interface, uint32_t version)
{
std::cout << "Registry has " << interface << std::endl;
registry_map[interface] = std::make_pair(id, version);
}
void Backend::registry_event_remove(uint32_t id)
{
for (auto it = registry_map.begin(); it != registry_map.end(); ++it) {
if (it->second.first == id) {
registry_map.erase(it);
return;
}
}
std::clog << "Registry removal failed, not found: " << id << std::endl;
}
void Backend::window_manager_pong(uint32_t serial)
{
xdg_wm_base_pong(window_manager, serial);
}
+80
View File
@@ -0,0 +1,80 @@
#pragma once
#include "wiWaylandWindow.h"
#include <wayland/wayland-client.h>
#include <map>
#include <string>
#include <iostream>
#include "xdg-decoration-unstable-v1.h"
#include "xdg-shell.h"
extern "C" {
struct xdg_wm_base;
struct zxdg_decoration_manager_v1;
}
namespace wi::wayland {
class Window;
class Backend {
private:
wl_display* display = nullptr;
wl_registry* registry = nullptr;
wl_registry_listener registry_listener;
// interface name -> id, version
std::map<std::string, std::pair<uint32_t, uint32_t>> registry_map;
wl_compositor* compositor = nullptr;
xdg_wm_base* window_manager = nullptr;
xdg_wm_base_listener window_manager_listener;
zxdg_decoration_manager_v1 *decoration_manager = nullptr;
public:
Window window;
public:
Backend() = default;
bool Init();
~Backend() { DeInit(); }
void DeInit();
bool CreateWindow(const char* title);
int dispatch();
int roundtrip();
// callbacks
void registry_event_add(uint32_t id, const char* interface, uint32_t version);
void registry_event_remove(uint32_t id);
void window_manager_pong(uint32_t serial);
private:
bool init_registry();
bool registry_has(const char* interface_name) const;
template<typename T>
T* bind(const char* interface_name, const struct wl_interface *interface, uint32_t version = -1)
{
std::pair<uint32_t, uint32_t> reg = registry_map.at(interface_name);
if (version < 0) {
version = reg.second;
} else {
version = 1;
}
void* r = wl_registry_bind(registry, reg.first, interface, version);
if (r == nullptr) {
std::clog<< "ERROR loading interface \"" << interface_name << '"' << std::endl;
}
return static_cast<T*>(r);
}
bool bind_compositor();
bool bind_xdg_wm_base();
bool bind_decoration_manager();
bool init_window_manager();
friend class Window;
};
}
+15
View File
@@ -0,0 +1,15 @@
#pragma once
namespace wi::wayland {
template<typename T>
void safe_delete(T*& ptr, void(&deleter)(T*))
{
if (ptr != nullptr)
{
deleter(ptr);
ptr = nullptr;
}
}
}
+215
View File
@@ -0,0 +1,215 @@
#include "wiWaylandWindow.h"
#include "wiWaylandBackend.h"
#include "wayland-client-protocol.h"
#include "wiWaylandUtils.h"
#include "xdg-decoration-unstable-v1.h"
#include "xdg-shell.h"
#include <iostream>
#define VK_NO_PROTOTYPES
#include "Utility/vulkan/vulkan.h"
#include "Utility/vulkan/vulkan_wayland.h"
#include "Utility/volk.h"
using namespace wi::wayland;
extern "C" void _static_on_redraw(void *data,
wl_callback *wl_callback,
uint32_t time)
{
static_cast<Window*>(data)->on_redraw(wl_callback, time);
}
extern "C" void _static_on_enter(void *data,
wl_surface *wl_surface,
wl_output *output)
{
static_cast<Window*>(data)->on_enter(output);
}
extern "C" void _static_on_leave(void *data,
wl_surface *wl_surface,
wl_output *output)
{
static_cast<Window*>(data)->on_leave(output);
}
extern "C" void _static_xdg_surface_configure(void* data, xdg_surface* raw, uint32_t serial)
{
static_cast<Window*>(data)->on_xdg_surface_ack_configure(serial);
}
extern "C" void _static_toplevel_close(void *data, xdg_toplevel *xdg_toplevel)
{
static_cast<Window*>(data)->on_toplevel_close();
}
extern "C" void _static_toplevel_configure(void *data,
xdg_toplevel *xdg_toplevel,
int32_t width,
int32_t height,
wl_array *states)
{
static_cast<Window*>(data)->on_toplevel_configure(width, height, states);
}
extern "C" void _static_toplevel_configure_bounds(void *data,
xdg_toplevel *xdg_toplevel,
int32_t width,
int32_t height)
{
static_cast<Window*>(data)->on_toplevel_configure_bounds(width, height);
}
void Window::on_enter(wl_output *output)
{}
void Window::on_leave(wl_output *output)
{}
void Window::on_redraw(wl_callback *wl_callback, uint32_t time)
{
if(frame_callback != nullptr) {
wl_callback_destroy(frame_callback);
frame_callback = nullptr;
}
if (on_redraw_callback)
on_redraw_callback(this);
}
void Window::on_xdg_surface_ack_configure(uint32_t serial)
{
xdg_surface_ack_configure(XDGsurface, serial);
}
void Window::on_toplevel_close()
{
if (on_close) on_close(this);
}
void Window::on_toplevel_configure(int32_t width, int32_t height, wl_array* states)
{
desired_width = width;
desired_height = height;
}
void Window::on_toplevel_configure_bounds(int32_t width, int32_t height)
{}
bool Window::Init(Backend* backend, const char* title)
{
this->backend = backend;
// Surface
WLsurface = wl_compositor_create_surface(backend->compositor);
if (WLsurface == nullptr) {std::cerr << "Could not create surface from compositor" << std::endl; return false;}
WLsurface_listener.enter = &_static_on_enter;
WLsurface_listener.leave = &_static_on_leave;
frame_listener.done = &_static_on_redraw;
wl_surface_add_listener(WLsurface, &WLsurface_listener, this);
// XDG Surface
XDGsurface = xdg_wm_base_get_xdg_surface(backend->window_manager, WLsurface);
if (XDGsurface == nullptr) {std::cerr << "Could not create XDG surface from WL surface" << std::endl; return false;}
XDGsurface_listener.configure = &_static_xdg_surface_configure;
xdg_surface_add_listener(XDGsurface, &XDGsurface_listener, this);
// Top Level
toplevel = xdg_surface_get_toplevel(XDGsurface);
if (toplevel == nullptr) {std::cerr << "Could not create XDG surface from WL surface" << std::endl; return false;}
toplevel_listener.close = &_static_toplevel_close;
toplevel_listener.configure = &_static_toplevel_configure;
toplevel_listener.configure_bounds = &_static_toplevel_configure_bounds;
xdg_toplevel_add_listener(toplevel, &toplevel_listener, this);
// DecorationManager
toplevel_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(backend->decoration_manager, toplevel);
if (toplevel_decoration != nullptr)
{
zxdg_toplevel_decoration_v1_set_mode(toplevel_decoration, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
}
SetTitle(title);
return true;
}
void Window::Deinit()
{
safe_delete(frame_callback, wl_callback_destroy);
safe_delete(toplevel_decoration, zxdg_toplevel_decoration_v1_destroy);
safe_delete(toplevel, xdg_toplevel_destroy);
safe_delete(XDGsurface, xdg_surface_destroy);
safe_delete(WLsurface, wl_surface_destroy);
}
void Window::SetTitle(const char* title)
{
if (title == nullptr)
return;
if (toplevel == nullptr)
return;
xdg_toplevel_set_title(toplevel, title);
}
void Window::GetWindowCurrentSize(int32_t *width, int32_t *height)
{
*width = current_width;
*height = current_height;
}
bool Window::HasPendingResize() const
{
return desired_height > 0 || desired_height > 0;
}
bool Window::AcceptDesiredDimensions()
{
const bool has_pending_resize = HasPendingResize();
if (desired_width > 0)
{
current_width = desired_width;
desired_width = 0;
}
if (desired_height > 0)
{
current_height = desired_height;
desired_height = 0;
}
return has_pending_resize;
}
void Window::SetFullscreen(bool fullscreen)
{
if (fullscreen)
{
// wl_output output;
// xdg_toplevel_set_fullscreen(toplevel, &output);
}
else
{
xdg_toplevel_unset_fullscreen(toplevel);
}
}
VkResult Window::CreateVulkanSurface(VkInstance instance, VkSurfaceKHR* VKsurface)
{
PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR =
(PFN_vkCreateWaylandSurfaceKHR)vkGetInstanceProcAddr(
instance,
"vkCreateWaylandSurfaceKHR");
VkWaylandSurfaceCreateInfoKHR createInfo {};
createInfo.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
createInfo.pNext = nullptr;
createInfo.flags = 0;
createInfo.display = backend->display;
createInfo.surface = WLsurface;
const VkAllocationCallbacks* allocator = nullptr;
VkResult res = vkCreateWaylandSurfaceKHR(instance, &createInfo, allocator, VKsurface);
backend->roundtrip();
return res;
}
+71
View File
@@ -0,0 +1,71 @@
#pragma once
#include "wayland-client-core.h"
#include "wayland-client-protocol.h"
#include "xdg-decoration-unstable-v1.h"
#include "xdg-shell.h"
#include <functional>
#define VK_NO_PROTOTYPES
#include "Utility/vulkan/vulkan.h"
// #include "Utility/volk.h"
extern "C" {
struct xdg_wm_base;
struct zxdg_decoration_manager_v1;
}
namespace wi::wayland {
class Backend;
class Window {
private:
// reference variables
Backend* backend = nullptr;
// OWN variables
wl_surface *WLsurface = nullptr;
xdg_surface *XDGsurface = nullptr;
xdg_toplevel *toplevel = nullptr;
zxdg_toplevel_decoration_v1* toplevel_decoration = nullptr;
wl_callback* frame_callback = nullptr;
wl_surface_listener WLsurface_listener;
wl_callback_listener frame_listener;
xdg_surface_listener XDGsurface_listener;
xdg_toplevel_listener toplevel_listener;
int32_t current_width = 800;
int32_t current_height = 600;
int32_t desired_width = 0;
int32_t desired_height = 0;
public:
std::function<void(Window* window)> on_redraw_callback;
std::function<void(Window* window)> on_close;
public:
~Window() { Deinit(); }
void Deinit();
Window() = default;
bool Init(Backend* backend, const char* title = nullptr);
void SetTitle(const char* title);
void GetWindowCurrentSize(int32_t* width, int32_t* height);
bool HasPendingResize() const;
bool AcceptDesiredDimensions();
void SetFullscreen(bool fullscreen);
VkResult CreateVulkanSurface(VkInstance instance, VkSurfaceKHR* VKSurface);
// callbacks
void on_enter(wl_output *output);
void on_leave(wl_output *output);
void on_redraw(wl_callback *wl_callback, uint32_t time);
void on_xdg_surface_ack_configure(uint32_t serial);
void on_toplevel_close();
void on_toplevel_configure(int32_t width, int32_t height, wl_array *states);
void on_toplevel_configure_bounds(int32_t width, int32_t height);
};
}
+83
View File
@@ -0,0 +1,83 @@
#include <wiECS.h>
module;
#include "WickedEngine.h"
export module wicked_engine;
export namespace wi
{
using wi::Application;
using wi::GPUBVH;
using wi::EmittedParticleSystem;
using wi::HairParticleSystem;
using wi::Ocean;
using wi::Sprite;
using wi::SpriteFont;
using wi::Archive;
using wi::Color;
using wi::FadeManager;
using wi::Resource;
using wi::SpinLock;
using wi::Timer;
using wi::Canvas;
namespace ecs
{
using wi::ecs::Entity;
using wi::ecs::INVALID_ENTITY;
}
namespace gui
{
using wi::gui::GUI;
using wi::gui::EventArgs;
using wi::gui::Widget;
using wi::gui::Button;
using wi::gui::Label;
using wi::gui::TextInputField;
using wi::gui::Slider;
using wi::gui::CheckBox;
using wi::gui::ComboBox;
using wi::gui::Window;
using wi::gui::ColorPicker;
using wi::gui::TreeList;
}
namespace primitive
{
using wi::primitive::AABB;
using wi::primitive::Sphere;
using wi::primitive::Capsule;
using wi::primitive::Ray;
using wi::primitive::Frustum;
using wi::primitive::Hitbox2D;
}
namespace font
{
using wi::font::Params;
using wi::font::Alignment;
}
namespace image
{
using wi::image::Params;
using wi::image::STENCILMODE;
using wi::image::STENCILREFMODE;
using wi::image::SAMPLEMODE;
using wi::image::QUALITY;
}
namespace eventhandler
{
using wi::eventhandler::EVENT_THREAD_SAFE_POINT;
using wi::eventhandler::EVENT_RELOAD_SHADERS;
using wi::eventhandler::EVENT_SET_VSYNC;
}
namespace math
{
using wi::math::IDENTITY_MATRIX;
}
}
+4
View File
@@ -0,0 +1,4 @@
[Project]
CreatedFrom=CMakeLists.txt
Manager=KDevCMakeManager
Name=WickedEngine
+365
View File
@@ -0,0 +1,365 @@
/*
Copyright (c) 2017-2019, Feral Interactive
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Feral Interactive nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef CLIENT_GAMEMODE_H
#define CLIENT_GAMEMODE_H
/*
* GameMode supports the following client functions
* Requests are refcounted in the daemon
*
* int gamemode_request_start() - Request gamemode starts
* 0 if the request was sent successfully
* -1 if the request failed
*
* int gamemode_request_end() - Request gamemode ends
* 0 if the request was sent successfully
* -1 if the request failed
*
* GAMEMODE_AUTO can be defined to make the above two functions apply during static init and
* destruction, as appropriate. In this configuration, errors will be printed to stderr
*
* int gamemode_query_status() - Query the current status of gamemode
* 0 if gamemode is inactive
* 1 if gamemode is active
* 2 if gamemode is active and this client is registered
* -1 if the query failed
*
* int gamemode_request_start_for(pid_t pid) - Request gamemode starts for another process
* 0 if the request was sent successfully
* -1 if the request failed
* -2 if the request was rejected
*
* int gamemode_request_end_for(pid_t pid) - Request gamemode ends for another process
* 0 if the request was sent successfully
* -1 if the request failed
* -2 if the request was rejected
*
* int gamemode_query_status_for(pid_t pid) - Query status of gamemode for another process
* 0 if gamemode is inactive
* 1 if gamemode is active
* 2 if gamemode is active and this client is registered
* -1 if the query failed
*
* const char* gamemode_error_string() - Get an error string
* returns a string describing any of the above errors
*
* Note: All the above requests can be blocking - dbus requests can and will block while the daemon
* handles the request. It is not recommended to make these calls in performance critical code
*/
#include <stdbool.h>
#include <stdio.h>
#include <dlfcn.h>
#include <string.h>
#include <sys/types.h>
static char internal_gamemode_client_error_string[512] = { 0 };
/**
* Load libgamemode dynamically to dislodge us from most dependencies.
* This allows clients to link and/or use this regardless of runtime.
* See SDL3 for an example of the reasoning behind this in terms of
* dynamic versioning as well.
*/
static volatile int internal_libgamemode_loaded = 1;
/* Typedefs for the functions to load */
typedef int (*api_call_return_int)(void);
typedef const char *(*api_call_return_cstring)(void);
typedef int (*api_call_pid_return_int)(pid_t);
/* Storage for functors */
static api_call_return_int REAL_internal_gamemode_request_start = NULL;
static api_call_return_int REAL_internal_gamemode_request_end = NULL;
static api_call_return_int REAL_internal_gamemode_query_status = NULL;
static api_call_return_cstring REAL_internal_gamemode_error_string = NULL;
static api_call_pid_return_int REAL_internal_gamemode_request_start_for = NULL;
static api_call_pid_return_int REAL_internal_gamemode_request_end_for = NULL;
static api_call_pid_return_int REAL_internal_gamemode_query_status_for = NULL;
/**
* Internal helper to perform the symbol binding safely.
*
* Returns 0 on success and -1 on failure
*/
__attribute__((always_inline)) static inline int internal_bind_libgamemode_symbol(
void *handle, const char *name, void **out_func, size_t func_size, bool required)
{
void *symbol_lookup = NULL;
char *dl_error = NULL;
/* Safely look up the symbol */
symbol_lookup = dlsym(handle, name);
dl_error = dlerror();
if (required && (dl_error || !symbol_lookup)) {
snprintf(internal_gamemode_client_error_string,
sizeof(internal_gamemode_client_error_string),
"dlsym failed - %s",
dl_error);
return -1;
}
/* Have the symbol correctly, copy it to make it usable */
memcpy(out_func, &symbol_lookup, func_size);
return 0;
}
/**
* Loads libgamemode and needed functions
*
* Returns 0 on success and -1 on failure
*/
__attribute__((always_inline)) static inline int internal_load_libgamemode(void)
{
/* We start at 1, 0 is a success and -1 is a fail */
if (internal_libgamemode_loaded != 1) {
return internal_libgamemode_loaded;
}
/* Anonymous struct type to define our bindings */
struct binding {
const char *name;
void **functor;
size_t func_size;
bool required;
} bindings[] = {
{ "real_gamemode_request_start",
(void **)&REAL_internal_gamemode_request_start,
sizeof(REAL_internal_gamemode_request_start),
true },
{ "real_gamemode_request_end",
(void **)&REAL_internal_gamemode_request_end,
sizeof(REAL_internal_gamemode_request_end),
true },
{ "real_gamemode_query_status",
(void **)&REAL_internal_gamemode_query_status,
sizeof(REAL_internal_gamemode_query_status),
false },
{ "real_gamemode_error_string",
(void **)&REAL_internal_gamemode_error_string,
sizeof(REAL_internal_gamemode_error_string),
true },
{ "real_gamemode_request_start_for",
(void **)&REAL_internal_gamemode_request_start_for,
sizeof(REAL_internal_gamemode_request_start_for),
false },
{ "real_gamemode_request_end_for",
(void **)&REAL_internal_gamemode_request_end_for,
sizeof(REAL_internal_gamemode_request_end_for),
false },
{ "real_gamemode_query_status_for",
(void **)&REAL_internal_gamemode_query_status_for,
sizeof(REAL_internal_gamemode_query_status_for),
false },
};
void *libgamemode = NULL;
/* Try and load libgamemode */
libgamemode = dlopen("libgamemode.so.0", RTLD_NOW);
if (!libgamemode) {
/* Attempt to load unversioned library for compatibility with older
* versions (as of writing, there are no ABI changes between the two -
* this may need to change if ever ABI-breaking changes are made) */
libgamemode = dlopen("libgamemode.so", RTLD_NOW);
if (!libgamemode) {
snprintf(internal_gamemode_client_error_string,
sizeof(internal_gamemode_client_error_string),
"dlopen failed - %s",
dlerror());
internal_libgamemode_loaded = -1;
return -1;
}
}
/* Attempt to bind all symbols */
for (size_t i = 0; i < sizeof(bindings) / sizeof(bindings[0]); i++) {
struct binding *binder = &bindings[i];
if (internal_bind_libgamemode_symbol(libgamemode,
binder->name,
binder->functor,
binder->func_size,
binder->required)) {
internal_libgamemode_loaded = -1;
return -1;
};
}
/* Success */
internal_libgamemode_loaded = 0;
return 0;
}
/**
* Redirect to the real libgamemode
*/
__attribute__((always_inline)) static inline const char *gamemode_error_string(void)
{
/* If we fail to load the system gamemode, or we have an error string already, return our error
* string instead of diverting to the system version */
if (internal_load_libgamemode() < 0 || internal_gamemode_client_error_string[0] != '\0') {
return internal_gamemode_client_error_string;
}
return REAL_internal_gamemode_error_string();
}
/**
* Redirect to the real libgamemode
* Allow automatically requesting game mode
* Also prints errors as they happen.
*/
#ifdef GAMEMODE_AUTO
__attribute__((constructor))
#else
__attribute__((always_inline)) static inline
#endif
int gamemode_request_start(void)
{
/* Need to load gamemode */
if (internal_load_libgamemode() < 0) {
#ifdef GAMEMODE_AUTO
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
#endif
return -1;
}
if (REAL_internal_gamemode_request_start() < 0) {
#ifdef GAMEMODE_AUTO
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
#endif
return -1;
}
return 0;
}
/* Redirect to the real libgamemode */
#ifdef GAMEMODE_AUTO
__attribute__((destructor))
#else
__attribute__((always_inline)) static inline
#endif
int gamemode_request_end(void)
{
/* Need to load gamemode */
if (internal_load_libgamemode() < 0) {
#ifdef GAMEMODE_AUTO
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
#endif
return -1;
}
if (REAL_internal_gamemode_request_end() < 0) {
#ifdef GAMEMODE_AUTO
fprintf(stderr, "gamemodeauto: %s\n", gamemode_error_string());
#endif
return -1;
}
return 0;
}
/* Redirect to the real libgamemode */
__attribute__((always_inline)) static inline int gamemode_query_status(void)
{
/* Need to load gamemode */
if (internal_load_libgamemode() < 0) {
return -1;
}
if (REAL_internal_gamemode_query_status == NULL) {
snprintf(internal_gamemode_client_error_string,
sizeof(internal_gamemode_client_error_string),
"gamemode_query_status missing (older host?)");
return -1;
}
return REAL_internal_gamemode_query_status();
}
/* Redirect to the real libgamemode */
__attribute__((always_inline)) static inline int gamemode_request_start_for(pid_t pid)
{
/* Need to load gamemode */
if (internal_load_libgamemode() < 0) {
return -1;
}
if (REAL_internal_gamemode_request_start_for == NULL) {
snprintf(internal_gamemode_client_error_string,
sizeof(internal_gamemode_client_error_string),
"gamemode_request_start_for missing (older host?)");
return -1;
}
return REAL_internal_gamemode_request_start_for(pid);
}
/* Redirect to the real libgamemode */
__attribute__((always_inline)) static inline int gamemode_request_end_for(pid_t pid)
{
/* Need to load gamemode */
if (internal_load_libgamemode() < 0) {
return -1;
}
if (REAL_internal_gamemode_request_end_for == NULL) {
snprintf(internal_gamemode_client_error_string,
sizeof(internal_gamemode_client_error_string),
"gamemode_request_end_for missing (older host?)");
return -1;
}
return REAL_internal_gamemode_request_end_for(pid);
}
/* Redirect to the real libgamemode */
__attribute__((always_inline)) static inline int gamemode_query_status_for(pid_t pid)
{
/* Need to load gamemode */
if (internal_load_libgamemode() < 0) {
return -1;
}
if (REAL_internal_gamemode_query_status_for == NULL) {
snprintf(internal_gamemode_client_error_string,
sizeof(internal_gamemode_client_error_string),
"gamemode_query_status_for missing (older host?)");
return -1;
}
return REAL_internal_gamemode_query_status_for(pid);
}
#endif // CLIENT_GAMEMODE_H
+4 -1
View File
@@ -743,7 +743,10 @@ namespace wi
}
#elif defined(PLATFORM_LINUX)
SDL_SetWindowFullscreen(window, fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
if (window.type == platform::LinuxWindow::eSDLWindow)
SDL_SetWindowFullscreen(window.sdl_window, fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
else if (window.type == platform::LinuxWindow::eWaylandWindow)
window.wl_window->SetFullscreen(fullscreen);
#endif // PLATFORM_WINDOWS_DESKTOP
}
+4 -4
View File
@@ -53,7 +53,7 @@ namespace wi
bool allow_hdr = true;
wi::graphics::SwapChain swapChain;
wi::Canvas canvas;
wi::platform::window_type window;
wi::platform::window_type window = nullptr;
// Runs the main engine loop
void Run();
@@ -75,13 +75,13 @@ namespace wi
// This is where the critical initializations happen (before any rendering or anything else)
virtual void Initialize();
// This is where application-wide updates get executed once per frame.
// This is where application-wide updates get executed once per frame.
// RenderPath::Update is also called from here for the active component
virtual void Update(float dt);
// This is where application-wide updates get executed in a fixed timestep based manner.
// This is where application-wide updates get executed in a fixed timestep based manner.
// RenderPath::FixedUpdate is also called from here for the active component
virtual void FixedUpdate();
// This is where application-wide rendering happens to offscreen buffers.
// This is where application-wide rendering happens to offscreen buffers.
// RenderPath::Render is also called from here for the active component
virtual void Render();
// This is where the application will render to the screen (backbuffer). It must render to the provided command list.
+40 -25
View File
@@ -1,4 +1,5 @@
#include "wiGraphicsDevice_Vulkan.h"
#include <wiPlatform.h>
#ifdef WICKEDENGINE_BUILD_VULKAN
#include "wiHelper.h"
@@ -23,6 +24,7 @@
#ifdef SDL2
#include <SDL2/SDL_vulkan.h>
#include "sdl2.h"
#include "Utility/vulkan/vulkan_wayland.h"
#endif
#include <string>
@@ -605,7 +607,7 @@ namespace vulkan_internal
}
VKAPI_ATTR VkBool32 VKAPI_CALL debugUtilsMessengerCallback(
VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
VkDebugUtilsMessageTypeFlagsEXT message_type,
const VkDebugUtilsMessengerCallbackDataEXT* callback_data,
void* user_data)
@@ -2442,18 +2444,25 @@ using namespace vulkan_internal;
instanceExtensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
#elif SDL2
{
uint32_t extensionCount;
SDL_Vulkan_GetInstanceExtensions(window, &extensionCount, nullptr);
wi::vector<const char *> extensionNames_sdl(extensionCount);
SDL_Vulkan_GetInstanceExtensions(window, &extensionCount, extensionNames_sdl.data());
instanceExtensions.reserve(instanceExtensions.size() + extensionNames_sdl.size());
for (auto& x : extensionNames_sdl)
if (window.type == platform::LinuxWindow::eSDLWindow)
{
instanceExtensions.push_back(x);
uint32_t extensionCount;
SDL_Vulkan_GetInstanceExtensions(window.sdl_window, &extensionCount, nullptr);
wi::vector<const char *> extensionNames_sdl(extensionCount);
SDL_Vulkan_GetInstanceExtensions(window.sdl_window, &extensionCount, extensionNames_sdl.data());
instanceExtensions.reserve(instanceExtensions.size() + extensionNames_sdl.size());
for (auto& x : extensionNames_sdl)
{
instanceExtensions.push_back(x);
}
}
else if (window.type == platform::LinuxWindow::eWaylandWindow)
{
instanceExtensions.push_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
}
}
#endif // _WIN32
if (validationMode != ValidationMode::Disabled)
{
// Determine the optimal validation layers to enable that are necessary for useful debugging
@@ -2966,7 +2975,7 @@ using namespace vulkan_internal;
queueFamiliesVideo[i].sType = VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR;
}
vkGetPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueFamilyCount, queueFamilies.data());
// Query base queue families:
for (uint32_t i = 0; i < queueFamilyCount; ++i)
{
@@ -3211,7 +3220,7 @@ using namespace vulkan_internal;
res = vmaCreateBuffer(allocationhandler->allocator, &bufferInfo, &allocInfo, &nullBuffer, &nullBufferAllocation, nullptr);
assert(res == VK_SUCCESS);
VkBufferViewCreateInfo viewInfo = {};
viewInfo.sType = VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO;
viewInfo.format = VK_FORMAT_R32G32B32A32_SFLOAT;
@@ -3680,7 +3689,7 @@ using namespace vulkan_internal;
res = vkGetPipelineCacheData(device, pipelineCache, &size, nullptr);
assert(res == VK_SUCCESS);
// Get data of pipeline cache
// Get data of pipeline cache
wi::vector<uint8_t> data(size);
res = vkGetPipelineCacheData(device, pipelineCache, &size, data.data());
assert(res == VK_SUCCESS);
@@ -3688,7 +3697,7 @@ using namespace vulkan_internal;
// Write pipeline cache data to a file in binary format
wi::helper::FileWrite(get_shader_cache_path(), data.data(), size);
// Destroy Vulkan pipeline cache
// Destroy Vulkan pipeline cache
vkDestroyPipelineCache(device, pipelineCache, nullptr);
pipelineCache = VK_NULL_HANDLE;
}
@@ -3725,9 +3734,15 @@ using namespace vulkan_internal;
res = vkCreateWin32SurfaceKHR(instance, &createInfo, nullptr, &internal_state->surface);
assert(res == VK_SUCCESS);
#elif SDL2
if (!SDL_Vulkan_CreateSurface(window, instance, &internal_state->surface))
if (window.type == platform::LinuxWindow::eSDLWindow) {
if (!SDL_Vulkan_CreateSurface(window.sdl_window, instance, &internal_state->surface))
{
throw sdl2::SDLError("Error creating a vulkan surface");
}
}
else if (window.type == platform::LinuxWindow::eWaylandWindow)
{
throw sdl2::SDLError("Error creating a vulkan surface");
assert(window.wl_window->CreateVulkanSurface(instance, &internal_state->surface) == VK_SUCCESS);
}
#else
#error WICKEDENGINE VULKAN DEVICE ERROR: PLATFORM NOT SUPPORTED
@@ -4071,7 +4086,7 @@ using namespace vulkan_internal;
dependencyInfo.pBufferMemoryBarriers = &barrier;
vkCmdPipelineBarrier2(cmd.transitionCommandBuffer, &dependencyInfo);
copyAllocator.submit(cmd);
}
}
@@ -5445,7 +5460,7 @@ using namespace vulkan_internal;
default:
break;
}
}
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {};
@@ -6423,7 +6438,7 @@ using namespace vulkan_internal;
info.referencePictureFormat = info.pictureFormat;
info.pVideoProfile = &video_capability_h264.profile;
info.pStdHeaderVersion = &video_capability_h264.video_capabilities.stdHeaderVersion;
res = vkCreateVideoSessionKHR(device, &info, nullptr, &internal_state->video_session);
assert(res == VK_SUCCESS);
@@ -7030,7 +7045,7 @@ using namespace vulkan_internal;
VkResult res = vkGetRayTracingShaderGroupHandlesKHR(device, to_internal(rtpso)->pipeline, group_index, 1, SHADER_IDENTIFIER_SIZE, dest);
assert(res == VK_SUCCESS);
}
void GraphicsDevice_Vulkan::SetName(GPUResource* pResource, const char* name) const
{
if (!debugUtils || pResource == nullptr || !pResource->IsValid())
@@ -7374,7 +7389,7 @@ using namespace vulkan_internal;
}
allocationhandler->destroylocker.unlock();
// Destroy Vulkan pipeline cache
// Destroy Vulkan pipeline cache
vkDestroyPipelineCache(device, pipelineCache, nullptr);
pipelineCache = VK_NULL_HANDLE;
@@ -7696,7 +7711,7 @@ using namespace vulkan_internal;
assert(0);
}
commandlist.prev_swapchains.push_back(*swapchain);
VkRenderingInfo info = {};
info.sType = VK_STRUCTURE_TYPE_RENDERING_INFO;
info.renderArea.offset.x = 0;
@@ -7935,7 +7950,7 @@ using namespace vulkan_internal;
barrier.newLayout = _ConvertImageLayout(image.layout);
assert(barrier.newLayout != VK_IMAGE_LAYOUT_UNDEFINED);
barrier.srcStageMask = _ConvertPipelineStage(image.layout_before);
barrier.dstStageMask = _ConvertPipelineStage(image.layout);
barrier.srcAccessMask = _ParseResourceState(image.layout_before);
@@ -9088,7 +9103,7 @@ using namespace vulkan_internal;
raygen.deviceAddress += desc->ray_generation.offset;
raygen.size = desc->ray_generation.size;
raygen.stride = raygen.size; // raygen specifically must be size == stride
VkStridedDeviceAddressRegionKHR miss = {};
miss.deviceAddress = desc->miss.buffer ? to_internal(desc->miss.buffer)->address : 0;
miss.deviceAddress += desc->miss.offset;
@@ -9113,8 +9128,8 @@ using namespace vulkan_internal;
&miss,
&hitgroup,
&callable,
desc->width,
desc->height,
desc->width,
desc->height,
desc->depth
);
}
+3
View File
@@ -18,6 +18,9 @@
#define VK_NO_PROTOTYPES
#include "Utility/vulkan/vulkan.h"
#ifdef SDL2
#include "Utility/vulkan/vulkan_wayland.h"
#endif
#include "Utility/volk.h"
#include "Utility/vk_mem_alloc.h"
+24 -22
View File
@@ -80,7 +80,7 @@ namespace wi::input
const KeyboardState& GetKeyboardState() { return keyboard; }
const MouseState& GetMouseState() { return mouse; }
struct Input
struct Input
{
BUTTON button = BUTTON_NONE;
int playerIndex = 0;
@@ -155,7 +155,7 @@ namespace wi::input
#if defined(_WIN32) && !defined(PLATFORM_XBOX)
wi::input::rawinput::GetMouseState(&mouse); // currently only the relative data can be used from this
wi::input::rawinput::GetKeyboardState(&keyboard);
wi::input::rawinput::GetKeyboardState(&keyboard);
// apparently checking the mouse here instead of Down() avoids missing the button presses (review!)
mouse.left_button_press |= KEY_DOWN(VK_LBUTTON);
@@ -474,15 +474,15 @@ namespace wi::input
switch (button)
{
case wi::input::MOUSE_BUTTON_LEFT:
if (mouse.left_button_press)
if (mouse.left_button_press)
return true;
return false;
case wi::input::MOUSE_BUTTON_RIGHT:
if (mouse.right_button_press)
if (mouse.right_button_press)
return true;
return false;
case wi::input::MOUSE_BUTTON_MIDDLE:
if (mouse.middle_button_press)
if (mouse.middle_button_press)
return true;
return false;
#ifdef _WIN32
@@ -507,7 +507,7 @@ namespace wi::input
case wi::input::KEYBOARD_BUTTON_LSHIFT:
keycode = VK_LSHIFT;
break;
case wi::input::KEYBOARD_BUTTON_F1:
case wi::input::KEYBOARD_BUTTON_F1:
keycode = VK_F1;
break;
case wi::input::KEYBOARD_BUTTON_F2:
@@ -718,22 +718,24 @@ namespace wi::input
ClientToScreen(hWnd, &p);
SetCursorPos(p.x, p.y);
#elif defined(SDL2)
// Keeping with the trend of 'Set Pointer' API on different platforms,
// SDL_WarpMouseInWindow is used in the case of SDL2. This unfortunately
// causes SDL2 to generate a mouse event for the delta between the old
// and new positions leading to 'rubber banding'.
// The current solution is to artifically generate a motion event of our own
// which will 'undo' this unwanted motion event during the mouse motion
// accumulation in wiSDLInput.cpp Update()
XMFLOAT4 currentPointer = GetPointer();
SDL_MouseMotionEvent motionEvent = {0};
motionEvent.type = SDL_MOUSEMOTION;
motionEvent.x = motionEvent.y = 0; // doesn't matter
motionEvent.xrel = currentPointer.x - props.x;
motionEvent.yrel = currentPointer.y - props.y;
SDL_PushEvent((SDL_Event*)&motionEvent);
SDL_WarpMouseInWindow(window, props.x, props.y);
if (window.type == platform::LinuxWindow::eSDLWindow)
{
// Keeping with the trend of 'Set Pointer' API on different platforms,
// SDL_WarpMouseInWindow is used in the case of SDL2. This unfortunately
// causes SDL2 to generate a mouse event for the delta between the old
// and new positions leading to 'rubber banding'.
// The current solution is to artifically generate a motion event of our own
// which will 'undo' this unwanted motion event during the mouse motion
// accumulation in wiSDLInput.cpp Update()
XMFLOAT4 currentPointer = GetPointer();
SDL_MouseMotionEvent motionEvent = {0};
motionEvent.type = SDL_MOUSEMOTION;
motionEvent.x = motionEvent.y = 0; // doesn't matter
motionEvent.xrel = currentPointer.x - props.x;
motionEvent.yrel = currentPointer.y - props.y;
SDL_PushEvent((SDL_Event*)&motionEvent);
SDL_WarpMouseInWindow(window.sdl_window, props.x, props.y);
}
#endif // SDL2
}
void HidePointer(bool value)
+32 -5
View File
@@ -34,6 +34,7 @@ typedef void* HMODULE;
#include <SDL2/SDL.h>
#include <SDL_vulkan.h>
#include "sdl2.h"
#include "Wayland/wiWaylandWindow.h"
#endif
@@ -42,7 +43,25 @@ namespace wi::platform
#ifdef _WIN32
using window_type = HWND;
#elif SDL2
using window_type = SDL_Window*;
struct LinuxWindow {
enum ELinuxWindowType {
eNoneWindow,
eSDLWindow,
eWaylandWindow,
} type;
union {
void* null;
SDL_Window* sdl_window;
wi::wayland::Window* wl_window;
};
LinuxWindow(std::nullptr_t)
: type(eNoneWindow), null(nullptr) {}
LinuxWindow(SDL_Window* window)
: type(eSDLWindow), sdl_window(window) {}
LinuxWindow(wi::wayland::Window* window)
: type(eWaylandWindow), wl_window(window) {}
};
using window_type = LinuxWindow;
#else
using window_type = void*;
#endif // _WIN32
@@ -83,10 +102,18 @@ namespace wi::platform
#endif // PLATFORM_WINDOWS_DESKTOP || PLATFORM_XBOX
#ifdef PLATFORM_LINUX
int window_width, window_height;
SDL_GetWindowSize(window, &window_width, &window_height);
SDL_Vulkan_GetDrawableSize(window, &dest->width, &dest->height);
dest->dpi = ((float)dest->width / (float)window_width) * 96.f;
if (window.type == window.eSDLWindow)
{
int window_width, window_height;
SDL_GetWindowSize(window.sdl_window, &window_width, &window_height);
SDL_Vulkan_GetDrawableSize(window.sdl_window, &dest->width, &dest->height);
dest->dpi = ((float)dest->width / (float)window_width) * 96.f;
}
else if (window.type == window.eWaylandWindow)
{
window.wl_window->GetWindowCurrentSize(&dest->width, &dest->height);
dest->dpi = 96.f;
}
#endif // PLATFORM_LINUX
}
}