Vulkan device initialization and compilation utils
- Vulkan initialization moved to InitVulkan() - Renderer thread processes commands from main thread - SetupDevice() for select physical device and queue families, create logical device and queues.
This commit is contained in:
parent
0062aa85e5
commit
721e5afbac
BIN
assets/fonts/ARIAL.TTF
Normal file
BIN
assets/fonts/ARIAL.TTF
Normal file
Binary file not shown.
108
assets/layout/base.rcss
Normal file
108
assets/layout/base.rcss
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
body, div,
|
||||||
|
h1, h2, h3, h4,
|
||||||
|
h5, h6, p,
|
||||||
|
hr, pre,
|
||||||
|
tabset tabs
|
||||||
|
{
|
||||||
|
display: block;
|
||||||
|
background-color: white;
|
||||||
|
color: black;
|
||||||
|
font-family: Arial;
|
||||||
|
}
|
||||||
|
|
||||||
|
rml, html,
|
||||||
|
body
|
||||||
|
{
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
margin: 0;
|
||||||
|
background-color: rgb(255, 255, 255);
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1
|
||||||
|
{
|
||||||
|
font-size: 2em;
|
||||||
|
margin: .67em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2
|
||||||
|
{
|
||||||
|
font-size: 1.5em;
|
||||||
|
margin: .75em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3
|
||||||
|
{
|
||||||
|
font-size: 1.17em;
|
||||||
|
margin: .83em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4, p
|
||||||
|
{
|
||||||
|
margin: 1.12em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h5
|
||||||
|
{
|
||||||
|
font-size: .83em;
|
||||||
|
margin: 1.5em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h6
|
||||||
|
{
|
||||||
|
font-size: .75em;
|
||||||
|
margin: 1.67em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4,
|
||||||
|
h5, h6, strong
|
||||||
|
{
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
em
|
||||||
|
{
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre
|
||||||
|
{
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr
|
||||||
|
{
|
||||||
|
border-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table
|
||||||
|
{
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: table;
|
||||||
|
}
|
||||||
|
tr
|
||||||
|
{
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: table-row;
|
||||||
|
}
|
||||||
|
td
|
||||||
|
{
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: table-cell;
|
||||||
|
}
|
||||||
|
col
|
||||||
|
{
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: table-column;
|
||||||
|
}
|
||||||
|
colgroup
|
||||||
|
{
|
||||||
|
display: table-column-group;
|
||||||
|
}
|
||||||
|
thead, tbody, tfoot
|
||||||
|
{
|
||||||
|
display: table-row-group;
|
||||||
|
}
|
||||||
13
assets/layout/test/test.rml
Normal file
13
assets/layout/test/test.rml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<rml>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<link type="text/css" href="../base.rcss" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<p>Hello World!</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</rml>
|
||||||
@ -41,23 +41,39 @@ target_link_libraries(
|
|||||||
$<IF:$<TARGET_EXISTS:SDL2::SDL2>,SDL2::SDL2,SDL2::SDL2-static>
|
$<IF:$<TARGET_EXISTS:SDL2::SDL2>,SDL2::SDL2,SDL2::SDL2-static>
|
||||||
)
|
)
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE Vulkan::Vulkan)
|
target_link_libraries(${PROJECT_NAME} PRIVATE Vulkan::Vulkan)
|
||||||
|
|
||||||
set(RMLUI_BACKEND_PATH ${RmlUi_SOURCE_DIR}/Backends) # Link SDL Vulkan backend for RmlUi
|
|
||||||
add_library(rmlui_backend_SDL_VK INTERFACE)
|
|
||||||
target_sources(rmlui_backend_SDL_VK INTERFACE
|
|
||||||
${RMLUI_BACKEND_PATH}/RmlUi_Platform_SDL.cpp
|
|
||||||
${RMLUI_BACKEND_PATH}/RmlUi_Renderer_VK.cpp
|
|
||||||
)
|
|
||||||
target_include_directories(rmlui_backend_SDL_VK INTERFACE ${RMLUI_BACKEND_PATH})
|
|
||||||
target_compile_definitions(rmlui_backend_SDL_VK INTERFACE
|
|
||||||
RMLUI_SDL_VERSION_MAJOR=2
|
|
||||||
RMLUI_NUM_MSAA_SAMPLES=4
|
|
||||||
RMLUI_VK_CUSTOM_LOADER=<vulkan/vulkan.h>
|
|
||||||
)
|
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE RmlUi::RmlUi)
|
target_link_libraries(${PROJECT_NAME} PRIVATE RmlUi::RmlUi)
|
||||||
|
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC include/)
|
target_include_directories(${PROJECT_NAME} PUBLIC include/)
|
||||||
|
|
||||||
if (CMAKE_VERSION VERSION_GREATER 3.12)
|
if (CMAKE_VERSION VERSION_GREATER 3.12)
|
||||||
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20)
|
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Compile options
|
||||||
|
if (APP_VERSION)
|
||||||
|
string(REPLACE "." ";" APP_VERSION_LIST ${APP_VERSION})
|
||||||
|
list(GET APP_VERSION_LIST 0 MAJOR_VERSION)
|
||||||
|
list(GET APP_VERSION_LIST 1 MINOR_VERSION)
|
||||||
|
list(GET APP_VERSION_LIST 2 PATCH_VERSION)
|
||||||
|
target_compile_definitions(${PROJECT_NAME}
|
||||||
|
PRIVATE APP_VERSION
|
||||||
|
PRIVATE MAJOR_VERSION=${MAJOR_VERSION}
|
||||||
|
PRIVATE MINOR_VERSION=${MINOR_VERSION}
|
||||||
|
PRIVATE PATCH_VERSION=${PATCH_VERSION}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (VALIDATION_LAYER)
|
||||||
|
target_compile_definitions(${PROJECT_NAME} PRIVATE VALIDATION_LAYER_ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Set a symbolic link so executable can find the /assets folder
|
||||||
|
set(link_src "${CMAKE_SOURCE_DIR}/assets")
|
||||||
|
set(link_dst "${CMAKE_CURRENT_BINARY_DIR}/assets")
|
||||||
|
add_custom_command(
|
||||||
|
TARGET ${PROJECT_NAME}
|
||||||
|
POST_BUILD COMMAND ${CMAKE_COMMAND}
|
||||||
|
-E create_symlink ${link_src} ${link_dst}
|
||||||
|
DEPENDS ${link_dst}
|
||||||
|
COMMENT "symbolic link ${link_src} => ${link_dst}"
|
||||||
|
)
|
||||||
@ -1,12 +1,41 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <optional>
|
||||||
|
#include <Boost/lockfree/spsc_queue.hpp>
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include <SDL2/SDL_vulkan.h>
|
#include <SDL2/SDL_vulkan.h>
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.hpp>
|
||||||
#include <RmlUi/Core.h>
|
#include <RmlUi/Core.h>
|
||||||
|
|
||||||
|
#ifdef VALIDATION_LAYER_ON
|
||||||
|
#define VALIDATION_LAYER "VK_LAYER_KHRONOS_validation"
|
||||||
|
#else
|
||||||
|
#define VALIDATION_LAYER
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// GPU properties priority for selection
|
||||||
|
#define GPU_DISCRETE_PRIORITY 1000
|
||||||
|
|
||||||
|
struct RenderCommand
|
||||||
|
{
|
||||||
|
enum Type
|
||||||
|
{
|
||||||
|
NONE,
|
||||||
|
|
||||||
|
//STORE screenHeight and screenWidth BEFORE request
|
||||||
|
RESIZE_WINDOW,
|
||||||
|
SHUTDOWN
|
||||||
|
} type = NONE;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QueueFamiliesBundle
|
||||||
|
{
|
||||||
|
std::optional<uint32_t> graphics;
|
||||||
|
std::optional<uint32_t> presence;
|
||||||
|
};
|
||||||
|
|
||||||
class Renderer
|
class Renderer
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@ -14,18 +43,35 @@ private:
|
|||||||
std::jthread renderThread;
|
std::jthread renderThread;
|
||||||
|
|
||||||
SDL_Window *window;
|
SDL_Window *window;
|
||||||
|
|
||||||
VkInstance vulkan;
|
VkInstance vulkan;
|
||||||
|
VkPhysicalDevice gpu;
|
||||||
|
VkDevice device;
|
||||||
|
QueueFamiliesBundle queueFamilies;
|
||||||
|
const float defaultQueuePriority = 1.0f;
|
||||||
|
|
||||||
Rml::Context *uiContext;
|
Rml::Context *uiContext;
|
||||||
|
|
||||||
|
boost::lockfree::spsc_queue<RenderCommand, boost::lockfree::capacity<512>> commands;
|
||||||
|
|
||||||
|
void InitVulkan();
|
||||||
|
void SetupDevice();
|
||||||
|
|
||||||
void Threading();
|
void Threading();
|
||||||
void Loop();
|
void Loop();
|
||||||
|
void ProcessCommand(const RenderCommand &command);
|
||||||
void Release();
|
void Release();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::atomic<bool> isRunning;
|
std::atomic<bool> isRunning;
|
||||||
|
std::atomic<int> screenWidth, screenHeight;
|
||||||
|
|
||||||
Renderer(SDL_Window *window);
|
Renderer(SDL_Window *window);
|
||||||
|
~Renderer();
|
||||||
|
|
||||||
void Start();
|
void Start();
|
||||||
void Stop();
|
void Shutdown();
|
||||||
|
|
||||||
|
void Request(const RenderCommand &command);
|
||||||
|
void Request(RenderCommand::Type type);
|
||||||
};
|
};
|
||||||
13
frontend/include/compile_config.hpp
Normal file
13
frontend/include/compile_config.hpp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if !_DEBUG | NDEBUG
|
||||||
|
#define P7_SINK L"/P7.Sink=FileTxt"
|
||||||
|
#else
|
||||||
|
#define P7_SINK L"/P7.Sink=Console"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !APP_VERSION
|
||||||
|
#define MAJOR_VERSION 0
|
||||||
|
#define MINOR_VERSION 0
|
||||||
|
#define PATCH_VERSION 0
|
||||||
|
#endif
|
||||||
@ -1,14 +1,216 @@
|
|||||||
|
#if !APP_VERSION
|
||||||
|
#include "compile_config.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "Renderer.hpp"
|
#include "Renderer.hpp"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include <allocator.hpp>
|
#include <allocator.hpp>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
Renderer::Renderer(SDL_Window *window) : isRunning(false)
|
Renderer::Renderer(SDL_Window *window) : isRunning(false)
|
||||||
{
|
{
|
||||||
this->window = window;
|
this->window = window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Renderer::~Renderer()
|
||||||
|
{
|
||||||
|
Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::InitVulkan()
|
||||||
|
{
|
||||||
|
std::vector<const char*> vulkanExtensions {
|
||||||
|
//
|
||||||
|
};
|
||||||
|
std::vector<const char*> vulkanLayers {
|
||||||
|
VALIDATION_LAYER
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get Vulkan extensions list
|
||||||
|
uint32_t extensionsSDLCount = 0;
|
||||||
|
if ( !SDL_Vulkan_GetInstanceExtensions(window, &extensionsSDLCount, nullptr) )
|
||||||
|
LOG(CRITICAL, "Fail to get SDL Vulkan extensions number! %hs", SDL_GetError());
|
||||||
|
|
||||||
|
std::vector<const char*> vulkanExtensionsSDL(extensionsSDLCount);
|
||||||
|
if ( !SDL_Vulkan_GetInstanceExtensions(window, &extensionsSDLCount, vulkanExtensionsSDL.data()) )
|
||||||
|
{
|
||||||
|
LOG(CRITICAL, "Fail to register SDL Vulkan extensions! %hs", SDL_GetError());
|
||||||
|
vulkanExtensionsSDL.clear();
|
||||||
|
}
|
||||||
|
else vulkanExtensions.insert(vulkanExtensions.end(), vulkanExtensionsSDL.begin(), vulkanExtensionsSDL.end());
|
||||||
|
|
||||||
|
for (const char *extension : vulkanExtensions)
|
||||||
|
{
|
||||||
|
LOG(INFO, "%hs Vulkan extension registered", extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const char *layer : vulkanLayers)
|
||||||
|
{
|
||||||
|
LOG(INFO, "%hs Vulkan layer registered", layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create VkInstance
|
||||||
|
VkApplicationInfo vkAppConfig {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.pApplicationName = "Etredia Empires",
|
||||||
|
.applicationVersion = VK_MAKE_VERSION(MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION),
|
||||||
|
.pEngineName = "No Engine",
|
||||||
|
.engineVersion = VK_MAKE_VERSION(1, 0, 0),
|
||||||
|
.apiVersion = VK_API_VERSION_1_0
|
||||||
|
};
|
||||||
|
|
||||||
|
VkInstanceCreateInfo vkCreateConfig {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.pApplicationInfo = &vkAppConfig,
|
||||||
|
.enabledLayerCount = static_cast<uint32_t>(vulkanLayers.size()),
|
||||||
|
.ppEnabledLayerNames = vulkanLayers.data(),
|
||||||
|
.enabledExtensionCount = static_cast<uint32_t>(vulkanExtensions.size()),
|
||||||
|
.ppEnabledExtensionNames = vulkanExtensions.data(),
|
||||||
|
};
|
||||||
|
|
||||||
|
VkResult vkResult = vkCreateInstance(&vkCreateConfig, nullptr, &vulkan);
|
||||||
|
if (vkResult != VK_SUCCESS)
|
||||||
|
LOG(CRITICAL, "Vulkan is not instantiated! Code: %d", vkResult);
|
||||||
|
else LOG(INFO, "Vulkan is instantiated");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::SetupDevice()
|
||||||
|
{
|
||||||
|
// Select physical device and queue families
|
||||||
|
VkResult vkResult;
|
||||||
|
uint32_t devicesCount = 0;
|
||||||
|
vkResult = vkEnumeratePhysicalDevices(vulkan, &devicesCount, nullptr);
|
||||||
|
if (vkResult != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
LOG(CRITICAL, "Failed to enumerate physical devices. Code: %d", vkResult);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (devicesCount == 0)
|
||||||
|
{
|
||||||
|
LOG(CRITICAL, "No devices with Vulkan support found!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<VkPhysicalDevice> devices(devicesCount);
|
||||||
|
vkResult = vkEnumeratePhysicalDevices(vulkan, &devicesCount, devices.data());
|
||||||
|
if (vkResult != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
LOG(CRITICAL, "Failed to enumerate %d physical devices. Code: %d", devicesCount, vkResult);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG(INFO, "Found %d Vulkan compatible physical devices.", devices.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
gpu = VK_NULL_HANDLE;
|
||||||
|
VkPhysicalDeviceProperties deviceProperties {};
|
||||||
|
VkPhysicalDeviceFeatures deviceFeatures {};
|
||||||
|
VkPhysicalDeviceFeatures enabledFeatures {};
|
||||||
|
uint32_t best_priority = 0;
|
||||||
|
for (const VkPhysicalDevice &physicalDevice : devices)
|
||||||
|
{
|
||||||
|
uint32_t priority = 1;
|
||||||
|
|
||||||
|
vkGetPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
|
||||||
|
|
||||||
|
if (deviceFeatures.wideLines) enabledFeatures.wideLines = VK_TRUE; else continue;
|
||||||
|
if (deviceFeatures.independentBlend) enabledFeatures.independentBlend = VK_TRUE; else continue;
|
||||||
|
|
||||||
|
vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties);
|
||||||
|
|
||||||
|
uint32_t queueFamiliesCount = 0;
|
||||||
|
vkGetPhysicalDeviceQueueFamilyProperties(
|
||||||
|
physicalDevice,
|
||||||
|
&queueFamiliesCount,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
std::vector<VkQueueFamilyProperties> queueFamiliesProperties(queueFamiliesCount);
|
||||||
|
vkGetPhysicalDeviceQueueFamilyProperties(
|
||||||
|
physicalDevice,
|
||||||
|
&queueFamiliesCount,
|
||||||
|
queueFamiliesProperties.data()
|
||||||
|
);
|
||||||
|
|
||||||
|
uint32_t i = 0;
|
||||||
|
QueueFamiliesBundle queueFamiliesBuffer {};
|
||||||
|
for (const VkQueueFamilyProperties &familyProps : queueFamiliesProperties)
|
||||||
|
{
|
||||||
|
if (familyProps.queueFlags & VK_QUEUE_GRAPHICS_BIT)
|
||||||
|
{
|
||||||
|
queueFamiliesBuffer.graphics = i;
|
||||||
|
queueFamiliesBuffer.presence = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: if (vkGetPhysicalDeviceSurfaceSupportKHR(gpu, i, surface, value))
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!queueFamiliesBuffer.graphics.has_value() ||
|
||||||
|
!queueFamiliesBuffer.presence.has_value()
|
||||||
|
)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
|
||||||
|
if (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
|
||||||
|
priority += GPU_DISCRETE_PRIORITY;
|
||||||
|
|
||||||
|
if (priority > best_priority)
|
||||||
|
{
|
||||||
|
best_priority = priority;
|
||||||
|
gpu = physicalDevice;
|
||||||
|
queueFamilies = queueFamiliesBuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gpu == VK_NULL_HANDLE)
|
||||||
|
{
|
||||||
|
LOG(CRITICAL, "Failed to select suitable physical device");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create queues
|
||||||
|
VkDeviceQueueCreateInfo graphicsQueueCreateConfig {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.queueFamilyIndex = queueFamilies.graphics.value(),
|
||||||
|
.queueCount = 1,
|
||||||
|
.pQueuePriorities = &defaultQueuePriority
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create logical device
|
||||||
|
std::vector<const char*> deviceExtensions = {
|
||||||
|
"VK_KHR_swapchain"
|
||||||
|
};
|
||||||
|
|
||||||
|
VkDeviceCreateInfo deviceInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.queueCreateInfoCount = 1,
|
||||||
|
.pQueueCreateInfos = &graphicsQueueCreateConfig,
|
||||||
|
.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size()),
|
||||||
|
.ppEnabledExtensionNames = deviceExtensions.data(),
|
||||||
|
.pEnabledFeatures = &enabledFeatures,
|
||||||
|
};
|
||||||
|
|
||||||
|
vkResult = vkCreateDevice(gpu, &deviceInfo, nullptr, &device);
|
||||||
|
if (vkResult != VK_SUCCESS)
|
||||||
|
{
|
||||||
|
LOG(CRITICAL, "Failed to create logical device on %hs. Code: %d", deviceProperties.deviceName, vkResult);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else LOG(INFO, "%hs is selected for render", deviceProperties.deviceName);
|
||||||
|
}
|
||||||
|
|
||||||
void Renderer::Start()
|
void Renderer::Start()
|
||||||
{
|
{
|
||||||
|
if (isRunning) throw std::exception("Renderer can be started only once");
|
||||||
|
|
||||||
isRunning = true;
|
isRunning = true;
|
||||||
renderThread = std::jthread([this](std::stop_token stop) {
|
renderThread = std::jthread([this](std::stop_token stop) {
|
||||||
this->stoken = &stop;
|
this->stoken = &stop;
|
||||||
@ -20,43 +222,9 @@ void Renderer::Threading()
|
|||||||
{
|
{
|
||||||
Logger::trace->Register_Thread(L"Renderer", 0);
|
Logger::trace->Register_Thread(L"Renderer", 0);
|
||||||
LOG(INFO, "Renderer thread started");
|
LOG(INFO, "Renderer thread started");
|
||||||
|
|
||||||
// Setup Vulkan
|
|
||||||
uint32_t sdlExtensionsCount = 0;
|
|
||||||
if ( !SDL_Vulkan_GetInstanceExtensions(window, &sdlExtensionsCount, nullptr) )
|
|
||||||
LOG(CRITICAL, "Fail to get SDL Vulkan extensions number! %hs", SDL_GetError());
|
|
||||||
|
|
||||||
const char **sdlExtentions = AllocateArray<const char*>(sdlExtensionsCount);
|
|
||||||
|
|
||||||
if ( !SDL_Vulkan_GetInstanceExtensions(window, &sdlExtensionsCount, sdlExtentions) )
|
InitVulkan();
|
||||||
LOG(CRITICAL, "Fail to load SDL Vulkan extentions! %hs", SDL_GetError());
|
SetupDevice();
|
||||||
else LOG(INFO, "Load %d SDL Vulkan extenstions", sdlExtensionsCount);
|
|
||||||
|
|
||||||
VkInstanceCreateInfo vkCreateConfig = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
|
||||||
.enabledLayerCount = 0,
|
|
||||||
.enabledExtensionCount = sdlExtensionsCount,
|
|
||||||
.ppEnabledExtensionNames = sdlExtentions
|
|
||||||
};
|
|
||||||
|
|
||||||
VkResult vkCreateResult = vkCreateInstance(&vkCreateConfig, nullptr, &vulkan);
|
|
||||||
if (vkCreateResult != VK_SUCCESS)
|
|
||||||
LOG(CRITICAL, "Vulkan is not instantiated! Code: %d", vkCreateResult);
|
|
||||||
else LOG(INFO, "Vulkan is instantiated");
|
|
||||||
|
|
||||||
DeallocateArray(sdlExtentions);
|
|
||||||
|
|
||||||
//Setup RmlUi
|
|
||||||
if (!Rml::Initialise())
|
|
||||||
LOG(CRITICAL, "RmlUi initialization failed!");
|
|
||||||
else LOG(INFO, "RmlUi initialized");
|
|
||||||
|
|
||||||
int32_t screenWidth, screenHeight;
|
|
||||||
SDL_GetWindowSize(window, &screenWidth, &screenHeight);
|
|
||||||
uiContext = Rml::CreateContext("default", Rml::Vector2i(screenWidth, screenHeight));
|
|
||||||
if (!uiContext)
|
|
||||||
LOG(CRITICAL, "RmlUi context creation failed!");
|
|
||||||
else LOG(INFO, "RmlUi context created");
|
|
||||||
|
|
||||||
Loop();
|
Loop();
|
||||||
|
|
||||||
@ -65,25 +233,63 @@ void Renderer::Threading()
|
|||||||
|
|
||||||
void Renderer::Loop()
|
void Renderer::Loop()
|
||||||
{
|
{
|
||||||
|
RenderCommand commandBuffer;
|
||||||
while (!stoken->stop_requested())
|
while (!stoken->stop_requested())
|
||||||
{
|
{
|
||||||
/* */
|
while (commands.pop(commandBuffer))
|
||||||
LOG(DEBUG, "...");
|
{
|
||||||
Sleep(1000);
|
ProcessCommand(commandBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::Stop()
|
void Renderer::ProcessCommand(const RenderCommand &command)
|
||||||
|
{
|
||||||
|
switch(command.type)
|
||||||
|
{
|
||||||
|
case RenderCommand::SHUTDOWN:
|
||||||
|
{
|
||||||
|
LOG(INFO, "SHUTDOWN command");
|
||||||
|
Shutdown();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case RenderCommand::RESIZE_WINDOW:
|
||||||
|
{
|
||||||
|
LOG(INFO, "RESIZE_WINDOW command");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
LOG(WARNING, "Unhandled command. Type id: %d", command.type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::Shutdown()
|
||||||
{
|
{
|
||||||
renderThread.request_stop();
|
renderThread.request_stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Renderer::Request(const RenderCommand &command)
|
||||||
|
{
|
||||||
|
commands.push(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::Request(RenderCommand::Type type)
|
||||||
|
{
|
||||||
|
commands.push(RenderCommand {.type = type});
|
||||||
|
}
|
||||||
|
|
||||||
void Renderer::Release()
|
void Renderer::Release()
|
||||||
{
|
{
|
||||||
Rml::Shutdown();
|
vkDestroyDevice(device, nullptr);
|
||||||
vkDestroyInstance(vulkan, nullptr);
|
vkDestroyInstance(vulkan, nullptr);
|
||||||
|
|
||||||
isRunning = false;
|
LOG(INFO, "Renderer is released");
|
||||||
|
isRunning.store(false);
|
||||||
LOG(INFO, "Renderer released");
|
|
||||||
}
|
}
|
||||||
@ -1,15 +1,9 @@
|
|||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
|
#include "compile_config.hpp"
|
||||||
#include "Renderer.hpp"
|
#include "Renderer.hpp"
|
||||||
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
#define P7_SINK L"/P7.Sink=Console"
|
|
||||||
#else
|
|
||||||
#define P7_SINK L"/P7.Sink=FileTxt"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
IP7_Trace* Logger::trace;
|
IP7_Trace* Logger::trace;
|
||||||
|
|
||||||
int SDL_main(int argc, char **argv)
|
int SDL_main(int argc, char **argv)
|
||||||
@ -20,11 +14,13 @@ int SDL_main(int argc, char **argv)
|
|||||||
Logger::trace = P7_Create_Trace(p7client, L"TC 1");
|
Logger::trace = P7_Create_Trace(p7client, L"TC 1");
|
||||||
Logger::trace->Register_Thread(L"Main", 0);
|
Logger::trace->Register_Thread(L"Main", 0);
|
||||||
|
|
||||||
|
LOG(INFO, "Etredia Empires, v%d.%d.%d", MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION);
|
||||||
|
|
||||||
// Setup SDL
|
// Setup SDL
|
||||||
bool quit = false;
|
bool quit = false;
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
|
|
||||||
SDL_Init(SDL_INIT_VIDEO);
|
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_TIMER);
|
||||||
|
|
||||||
SDL_Window *window = SDL_CreateWindow(
|
SDL_Window *window = SDL_CreateWindow(
|
||||||
"Etredia Empires",
|
"Etredia Empires",
|
||||||
@ -34,6 +30,7 @@ int SDL_main(int argc, char **argv)
|
|||||||
600,
|
600,
|
||||||
SDL_WINDOW_VULKAN
|
SDL_WINDOW_VULKAN
|
||||||
);
|
);
|
||||||
|
SDL_StopTextInput();
|
||||||
|
|
||||||
if (!window)
|
if (!window)
|
||||||
{
|
{
|
||||||
@ -49,12 +46,13 @@ int SDL_main(int argc, char **argv)
|
|||||||
// Process SDL events
|
// Process SDL events
|
||||||
while(!quit)
|
while(!quit)
|
||||||
{
|
{
|
||||||
SDL_WaitEvent(&event);
|
SDL_PollEvent(&event);
|
||||||
|
|
||||||
switch(event.type)
|
switch(event.type)
|
||||||
{
|
{
|
||||||
case SDL_QUIT:
|
case SDL_QUIT:
|
||||||
{
|
{
|
||||||
|
SDL_RestoreWindow(window);
|
||||||
quit = true;
|
quit = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -65,8 +63,9 @@ int SDL_main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
case SDL_WINDOWEVENT_RESIZED:
|
case SDL_WINDOWEVENT_RESIZED:
|
||||||
{
|
{
|
||||||
//TODO: move to renderer
|
renderer.screenWidth.store(event.window.data1);
|
||||||
//uiContext->SetDimensions(Rml::Vector2i(event.window.data1, event.window.data2));
|
renderer.screenHeight.store(event.window.data2);
|
||||||
|
renderer.Request(RenderCommand::RESIZE_WINDOW);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,12 +73,12 @@ int SDL_main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free memory
|
// Free memory
|
||||||
LOG(INFO, "Exit...");
|
LOG(INFO, "Exit...");
|
||||||
renderer.Stop(); while(renderer.isRunning) {/* */}
|
renderer.Shutdown(); while(renderer.isRunning.load());
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
Logger::trace->Unregister_Thread(0);
|
Logger::trace->Unregister_Thread(0);
|
||||||
Logger::trace->Release();
|
Logger::trace->Release();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user