Refactor modules architecture
This commit is contained in:
parent
945cf4b1cc
commit
67b2b64d2f
@ -14,4 +14,4 @@ add_subdirectory(sdk/materials)
|
|||||||
add_subdirectory(utils)
|
add_subdirectory(utils)
|
||||||
add_subdirectory (p7lib)
|
add_subdirectory (p7lib)
|
||||||
add_subdirectory (ECSAPI)
|
add_subdirectory (ECSAPI)
|
||||||
add_subdirectory (frontend)
|
add_subdirectory (engine)
|
||||||
@ -8,7 +8,7 @@ endif()
|
|||||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
project (EEfrontend)
|
project (engine)
|
||||||
|
|
||||||
|
|
||||||
# List sources
|
# List sources
|
||||||
@ -25,9 +25,6 @@ file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS
|
|||||||
find_package(Boost REQUIRED COMPONENTS lockfree)
|
find_package(Boost REQUIRED COMPONENTS lockfree)
|
||||||
find_package(xxHash CONFIG REQUIRED)
|
find_package(xxHash CONFIG REQUIRED)
|
||||||
find_package(glfw3 CONFIG REQUIRED)
|
find_package(glfw3 CONFIG REQUIRED)
|
||||||
find_package(glm CONFIG REQUIRED)
|
|
||||||
find_package(Vulkan REQUIRED)
|
|
||||||
find_package(RmlUi CONFIG REQUIRED)
|
|
||||||
|
|
||||||
# Link library
|
# Link library
|
||||||
|
|
||||||
@ -39,9 +36,6 @@ target_link_libraries(${PROJECT_NAME} PRIVATE Boost::lockfree)
|
|||||||
target_link_libraries(${PROJECT_NAME} PRIVATE xxHash::xxhash)
|
target_link_libraries(${PROJECT_NAME} PRIVATE xxHash::xxhash)
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE p7)
|
target_link_libraries(${PROJECT_NAME} PRIVATE p7)
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE glfw)
|
target_link_libraries(${PROJECT_NAME} PRIVATE glfw)
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE glm::glm)
|
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE Vulkan::Vulkan)
|
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE RmlUi::RmlUi)
|
|
||||||
|
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC include/)
|
target_include_directories(${PROJECT_NAME} PUBLIC include/)
|
||||||
|
|
||||||
@ -63,10 +57,6 @@ if (APP_VERSION)
|
|||||||
)
|
)
|
||||||
endif()
|
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 a symbolic link so executable can find the /assets folder
|
||||||
set(link_src "${CMAKE_SOURCE_DIR}/assets")
|
set(link_src "${CMAKE_SOURCE_DIR}/assets")
|
||||||
set(link_dst "${CMAKE_CURRENT_BINARY_DIR}/assets")
|
set(link_dst "${CMAKE_CURRENT_BINARY_DIR}/assets")
|
||||||
@ -1,12 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "AssetManager.hpp"
|
#include "AssetManager.hpp"
|
||||||
#include "Renderer.hpp"
|
#include "RenderInterface.hpp"
|
||||||
|
|
||||||
class Engine
|
class Engine
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static AssetManager *assetManager;
|
static AssetManager *assetManager;
|
||||||
static Renderer *renderer;
|
static IRenderer *renderer;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Engine();
|
Engine();
|
||||||
53
engine/include/RenderInterface.hpp
Normal file
53
engine/include/RenderInterface.hpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <thread>
|
||||||
|
#include <atomic>
|
||||||
|
#include <Boost/lockfree/spsc_queue.hpp>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
struct RenderCommand
|
||||||
|
{
|
||||||
|
enum Type
|
||||||
|
{
|
||||||
|
NONE,
|
||||||
|
|
||||||
|
RESIZE_WINDOW,
|
||||||
|
SHUTDOWN
|
||||||
|
} type = NONE;
|
||||||
|
};
|
||||||
|
|
||||||
|
class IRenderer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IRenderer(GLFWwindow *window);
|
||||||
|
~IRenderer();
|
||||||
|
|
||||||
|
void Start();
|
||||||
|
void Shutdown();
|
||||||
|
|
||||||
|
bool GetThreadStatus();
|
||||||
|
bool GetDrawStatus();
|
||||||
|
|
||||||
|
void ResizeWindow(int width, int height);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::atomic<bool> isRunning;
|
||||||
|
std::atomic<bool> isDrawing;
|
||||||
|
std::atomic<int> screenWidth, screenHeight;
|
||||||
|
|
||||||
|
std::stop_token *stoken;
|
||||||
|
std::jthread renderThread;
|
||||||
|
boost::lockfree::spsc_queue<RenderCommand, boost::lockfree::capacity<512>> commands;
|
||||||
|
|
||||||
|
GLFWwindow *window;
|
||||||
|
|
||||||
|
virtual void Draw() = 0;
|
||||||
|
|
||||||
|
void Threading();
|
||||||
|
void Request(const RenderCommand &command);
|
||||||
|
void Request(const RenderCommand::Type &type);
|
||||||
|
virtual void Init() = 0;
|
||||||
|
virtual void Dispose() = 0;
|
||||||
|
void Loop();
|
||||||
|
void ProcessCommand(const RenderCommand &command);
|
||||||
|
void Release();
|
||||||
|
};
|
||||||
@ -1,4 +1,4 @@
|
|||||||
#include "Engine.hpp"
|
#include "Engine.hpp"
|
||||||
|
|
||||||
AssetManager* Engine::assetManager;
|
AssetManager* Engine::assetManager;
|
||||||
Renderer* Engine::renderer;
|
IRenderer* Engine::renderer;
|
||||||
119
engine/src/RenderInterface.cpp
Normal file
119
engine/src/RenderInterface.cpp
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
#include "RenderInterface.hpp"
|
||||||
|
#include "Logger.h"
|
||||||
|
#include <allocator.hpp>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
IRenderer::IRenderer(GLFWwindow *window) :
|
||||||
|
isRunning(false),
|
||||||
|
isDrawing(false)
|
||||||
|
{
|
||||||
|
this->window = window;
|
||||||
|
int width = -1, height = -1;
|
||||||
|
glfwGetFramebufferSize(window, &width, &height);
|
||||||
|
screenWidth.store(width);
|
||||||
|
screenHeight.store(height);
|
||||||
|
}
|
||||||
|
|
||||||
|
IRenderer::~IRenderer()
|
||||||
|
{
|
||||||
|
Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRenderer::Start()
|
||||||
|
{
|
||||||
|
if (isRunning)
|
||||||
|
{
|
||||||
|
LOG(CRITICAL, "Renderer can be started only once");
|
||||||
|
throw std::logic_error("Renderer can be started only once");
|
||||||
|
}
|
||||||
|
|
||||||
|
isRunning.store(true);
|
||||||
|
isDrawing.store(true);
|
||||||
|
renderThread = std::jthread([this](std::stop_token stop) {
|
||||||
|
this->stoken = &stop;
|
||||||
|
Threading();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRenderer::Threading()
|
||||||
|
{
|
||||||
|
Logger::trace->Register_Thread(L"Renderer", 0);
|
||||||
|
LOG(INFO, "Renderer thread started");
|
||||||
|
|
||||||
|
Init();
|
||||||
|
Loop();
|
||||||
|
Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void IRenderer::Loop()
|
||||||
|
{
|
||||||
|
RenderCommand commandBuffer;
|
||||||
|
while (!stoken->stop_requested())
|
||||||
|
{
|
||||||
|
while (commands.pop(commandBuffer))
|
||||||
|
{
|
||||||
|
ProcessCommand(commandBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
Draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRenderer::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 IRenderer::Shutdown()
|
||||||
|
{
|
||||||
|
renderThread.request_stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRenderer::Request(const RenderCommand &command)
|
||||||
|
{
|
||||||
|
commands.push(command);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRenderer::Request(const RenderCommand::Type &type)
|
||||||
|
{
|
||||||
|
commands.push(RenderCommand {.type = type});
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRenderer::ResizeWindow(int width, int height)
|
||||||
|
{
|
||||||
|
screenWidth.store(width);
|
||||||
|
screenHeight.store(height);
|
||||||
|
Request(RenderCommand::RESIZE_WINDOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRenderer::Release()
|
||||||
|
{
|
||||||
|
Dispose();
|
||||||
|
LOG(INFO, "Renderer is released");
|
||||||
|
isRunning.store(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IRenderer::GetThreadStatus() { return isRunning.load(); }
|
||||||
|
bool IRenderer::GetDrawStatus() { return isDrawing.load(); }
|
||||||
74
engine/src/main.cpp
Normal file
74
engine/src/main.cpp
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#include "Logger.h"
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
#include "compile_config.hpp"
|
||||||
|
#include "Engine.hpp"
|
||||||
|
|
||||||
|
IP7_Trace* Logger::trace;
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
// Setup P7 logger
|
||||||
|
IP7_Client *p7client = P7_Create_Client(P7_SINK);
|
||||||
|
P7_Set_Crash_Handler();
|
||||||
|
Logger::trace = P7_Create_Trace(p7client, L"TC 1");
|
||||||
|
Logger::trace->Register_Thread(L"Main", 0);
|
||||||
|
|
||||||
|
LOG(INFO, "Etredia Empires, v%d.%d.%d", MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION);
|
||||||
|
|
||||||
|
// Setup GLFW
|
||||||
|
glfwInit();
|
||||||
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||||
|
|
||||||
|
GLFWwindow *window = glfwCreateWindow(800, 600, "Etredia Empires", nullptr, nullptr);
|
||||||
|
|
||||||
|
if (!window)
|
||||||
|
LOG(CRITICAL, "GLFW Window failed");
|
||||||
|
else LOG(INFO, "GLFW Window created");
|
||||||
|
|
||||||
|
// Setup assets
|
||||||
|
AssetManager assetManager;
|
||||||
|
assetManager.Start();
|
||||||
|
assetManager.LoadShaders();
|
||||||
|
|
||||||
|
// Setup Renderer
|
||||||
|
// assetManager.LoadAsync(AssetInfo::MATERIAL, "assets/materials/helloworld.mat");
|
||||||
|
// AssetHandle baseMaterialHandle = assetManager.Find("assets/materials/helloworld.mat");
|
||||||
|
// AssetMaterial baseMaterial = assetManager.Get<AssetMaterial>(baseMaterialHandle);
|
||||||
|
// IRenderer renderer(window);
|
||||||
|
// renderer.Start();
|
||||||
|
|
||||||
|
//Setup Engine
|
||||||
|
Engine::assetManager = &assetManager;
|
||||||
|
//Engine::renderer = &renderer;
|
||||||
|
|
||||||
|
glfwSetFramebufferSizeCallback(window, [](GLFWwindow *window, int width, int height) {
|
||||||
|
Engine::renderer->ResizeWindow(width, height);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Process GLFW events
|
||||||
|
while(!glfwWindowShouldClose(window))
|
||||||
|
{
|
||||||
|
glfwPollEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free memory
|
||||||
|
LOG(INFO, "Exit...");
|
||||||
|
if (Engine::renderer != nullptr)
|
||||||
|
{ // Wait for renderer to clean and shutdown
|
||||||
|
Engine::renderer->Shutdown();
|
||||||
|
while(Engine::renderer->GetThreadStatus());
|
||||||
|
}
|
||||||
|
if (Engine::assetManager != nullptr)
|
||||||
|
{ // Wait for asset manager to clean and shutdown
|
||||||
|
Engine::assetManager->Shutdown();
|
||||||
|
while(Engine::assetManager->isRunning.load());
|
||||||
|
}
|
||||||
|
glfwDestroyWindow(window);
|
||||||
|
glfwTerminate();
|
||||||
|
Logger::trace->Unregister_Thread(0);
|
||||||
|
Logger::trace->Release();
|
||||||
|
p7client->Release();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -1,84 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <vulkan/vulkan.h>
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
#include <vector>
|
|
||||||
#include <array>
|
|
||||||
|
|
||||||
#define ATTRIBUTE_FORMAT_VEC2 VK_FORMAT_R32G32_SFLOAT
|
|
||||||
#define ATTRIBUTE_FORMAT_VEC3 VK_FORMAT_R32G32B32_SFLOAT
|
|
||||||
#define ATTRIBUTE_FORMAT_VEC4 VK_FORMAT_R32G32B32A32_SFLOAT
|
|
||||||
|
|
||||||
struct GPU_Transform
|
|
||||||
{
|
|
||||||
glm::vec3 pos = glm::vec3(0.0f, 0.0f, 0.0f);
|
|
||||||
glm::vec3 scale = glm::vec3(1.0f, 1.0f, 1.0f);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GPU_Vertex
|
|
||||||
{
|
|
||||||
glm::vec2 pos;
|
|
||||||
glm::vec3 color;
|
|
||||||
|
|
||||||
static std::array<VkVertexInputAttributeDescription, 2> GetAttributes();
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GPU_BufferSlot
|
|
||||||
{
|
|
||||||
size_t position;
|
|
||||||
size_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T> struct GPU_Buffer
|
|
||||||
{
|
|
||||||
T *data;
|
|
||||||
size_t size;
|
|
||||||
const size_t ELEMENT_SIZE;
|
|
||||||
std::vector<GPU_BufferSlot> freeSlots;
|
|
||||||
|
|
||||||
GPU_Buffer();
|
|
||||||
GPU_BufferSlot* FindFreeSlot(size_t size);
|
|
||||||
size_t Write(const T *elements, size_t elementsCount);
|
|
||||||
// void Clear(GPU_BufferSlot range);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Template definitions
|
|
||||||
|
|
||||||
template<typename T> GPU_Buffer<T>::GPU_Buffer() : ELEMENT_SIZE(sizeof(T))
|
|
||||||
{
|
|
||||||
freeSlots.push_back({.position = 0, .size = size});
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T> GPU_BufferSlot* GPU_Buffer<T>::FindFreeSlot(size_t size)
|
|
||||||
{
|
|
||||||
for (auto i = freeSlots.rbegin(); i != freeSlots.rend(); i++)
|
|
||||||
{
|
|
||||||
if (i->size >= size)
|
|
||||||
return &(*i);
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T> size_t GPU_Buffer<T>::Write(const T *elements, size_t elementsCount)
|
|
||||||
{
|
|
||||||
GPU_BufferSlot *slot = FindFreeSlot(elementsCount);
|
|
||||||
if (slot == nullptr) return 0;
|
|
||||||
|
|
||||||
memcpy(data + slot->position, elements, elementsCount * ELEMENT_SIZE);
|
|
||||||
|
|
||||||
slot->size -= elementsCount;
|
|
||||||
slot->position += elementsCount;
|
|
||||||
if (slot->size == 0)
|
|
||||||
freeSlots.pop_back();
|
|
||||||
|
|
||||||
return slot->position - elementsCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// template<typename T> void GPU_Buffer<T>::Clear(GPU_BufferSlot range)
|
|
||||||
// {
|
|
||||||
// freeSlots.push_back(range);
|
|
||||||
// //TODO: insert sorted by pos and combine intersections
|
|
||||||
// }
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "GPU_BaseTypes.hpp"
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
|
|
||||||
struct GPU_GlobalUBO
|
|
||||||
{
|
|
||||||
glm::mat4 view;
|
|
||||||
glm::mat4 proj;
|
|
||||||
float time;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GPU_TranformUBO
|
|
||||||
{
|
|
||||||
glm::mat4 model;
|
|
||||||
|
|
||||||
void Update(const GPU_Transform &tranform);
|
|
||||||
};
|
|
||||||
@ -1,81 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "AssetData.hpp"
|
|
||||||
#include <vulkan/vulkan.hpp>
|
|
||||||
#include <vector>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
#define PIPELINE_CREATE_NEW 0
|
|
||||||
#define PIPELINE_CREATE_DERIVED (1 << 0)
|
|
||||||
|
|
||||||
struct PipelineBinding
|
|
||||||
{
|
|
||||||
const AssetMaterial *baseMaterial;
|
|
||||||
|
|
||||||
const VkRenderPass *baseRenderPass;
|
|
||||||
const VkDevice *device;
|
|
||||||
const VkExtent2D *surfaceExtent;
|
|
||||||
|
|
||||||
const VkVertexInputBindingDescription *vertexBindingConfig;
|
|
||||||
uint32_t vertexAttributesCount;
|
|
||||||
const VkVertexInputAttributeDescription *vertexAttributesConfig;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PipelineConfig
|
|
||||||
{
|
|
||||||
VkPipelineVertexInputStateCreateInfo vertexInputConfig;
|
|
||||||
VkPipelineInputAssemblyStateCreateInfo inputAssemblyConfig;
|
|
||||||
VkPipelineViewportStateCreateInfo viewportStateConfig;
|
|
||||||
VkPipelineRasterizationStateCreateInfo rasterizerConfig;
|
|
||||||
VkPipelineMultisampleStateCreateInfo multisamplingConfig;
|
|
||||||
VkPipelineDepthStencilStateCreateInfo depthStencilConfig;
|
|
||||||
|
|
||||||
// SRC - new color, DST - old color
|
|
||||||
std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentConfigs;
|
|
||||||
VkPipelineColorBlendStateCreateInfo colorBlendConfig;
|
|
||||||
VkPipelineDynamicStateCreateInfo dynamicStateConfig;
|
|
||||||
VkPipelineLayoutCreateInfo pipelineLayoutConfig;
|
|
||||||
|
|
||||||
VkViewport defaultViewport;
|
|
||||||
VkRect2D defaultScissors;
|
|
||||||
std::vector<VkDynamicState> dynamicStates;
|
|
||||||
|
|
||||||
std::vector<VkDescriptorSetLayoutBinding> uniforms;
|
|
||||||
int vertexBindingsCount, fragmentBindingsCount;
|
|
||||||
VkDescriptorSetLayoutCreateInfo uniformsConfig;
|
|
||||||
|
|
||||||
VkGraphicsPipelineCreateInfo pipelineConfig;
|
|
||||||
|
|
||||||
PipelineConfig Copy() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Pipeline
|
|
||||||
{
|
|
||||||
VkPipeline instance;
|
|
||||||
VkPipelineLayout layout;
|
|
||||||
VkDescriptorSetLayout uniformsLayout;
|
|
||||||
VkViewport viewport;
|
|
||||||
VkRect2D scissors;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PipelineFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PipelineFactory(const PipelineBinding &binding);
|
|
||||||
~PipelineFactory();
|
|
||||||
|
|
||||||
Pipeline& Get(const AssetMaterial &material);
|
|
||||||
void Create(const AssetMaterial &material, const VkRenderPass &renderPass, const uint32_t &flags);
|
|
||||||
|
|
||||||
private:
|
|
||||||
PipelineBinding binding;
|
|
||||||
PipelineConfig basePipelineConfig;
|
|
||||||
|
|
||||||
Pipeline basePipeline;
|
|
||||||
std::unordered_map<const AssetMaterial*, Pipeline> pipelines;
|
|
||||||
|
|
||||||
const VkDevice &device;
|
|
||||||
const VkExtent2D &surfaceExtent;
|
|
||||||
|
|
||||||
const VkVertexInputBindingDescription &vertexBindingConfig;
|
|
||||||
|
|
||||||
};
|
|
||||||
@ -1,256 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <thread>
|
|
||||||
#include <atomic>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <vector>
|
|
||||||
#include <set>
|
|
||||||
#include <Boost/lockfree/spsc_queue.hpp>
|
|
||||||
|
|
||||||
#define GLFW_INCLUDE_VULKAN
|
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
|
|
||||||
#include "GPU_Types/GPU_BaseTypes.hpp"
|
|
||||||
|
|
||||||
#include "PipelineFactory.hpp"
|
|
||||||
|
|
||||||
#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
|
|
||||||
#define GPU_GRAPHICS_WITH_PRESENT_PRIORITY 500
|
|
||||||
#define GPU_B8G8R8_SRGB_PRIORITY 10
|
|
||||||
|
|
||||||
#define QUEUE_FAMILY_NO_VALUE UINT32_MAX
|
|
||||||
|
|
||||||
#define RENDER_PASS_BASE 438461662
|
|
||||||
#define RENDER_PASS_GUI
|
|
||||||
|
|
||||||
#define INDICES_SIZE uint16_t
|
|
||||||
#define INDICES_SIZE_VK VK_INDEX_TYPE_UINT16
|
|
||||||
|
|
||||||
struct Mesh
|
|
||||||
{
|
|
||||||
size_t verticesBufferPosition = 0;
|
|
||||||
size_t indicesBufferPosition = 0;
|
|
||||||
std::vector<GPU_Vertex> vertices;
|
|
||||||
std::vector<INDICES_SIZE> indices;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MaterialParams
|
|
||||||
{
|
|
||||||
VkDescriptorSet descriptors;
|
|
||||||
//TODO: push-constants
|
|
||||||
|
|
||||||
void Set(const char** param, const char** property = nullptr);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RenderObject
|
|
||||||
{
|
|
||||||
uint32_t engineId = UINT32_MAX;
|
|
||||||
|
|
||||||
// Multiple transforms for batching
|
|
||||||
std::vector<GPU_Transform> transforms;
|
|
||||||
uint8_t depth = 0;
|
|
||||||
Mesh mesh;
|
|
||||||
bool isUI = false;
|
|
||||||
//TODO: texture
|
|
||||||
|
|
||||||
AssetMaterial &material;
|
|
||||||
MaterialParams materialParams;
|
|
||||||
};
|
|
||||||
bool operator < (const RenderObject& lhs, const RenderObject& rhs);
|
|
||||||
|
|
||||||
struct RenderCommand
|
|
||||||
{
|
|
||||||
enum Type
|
|
||||||
{
|
|
||||||
NONE,
|
|
||||||
|
|
||||||
REGISTER_OBJECTS,
|
|
||||||
RESIZE_WINDOW,
|
|
||||||
SHUTDOWN
|
|
||||||
} type = NONE;
|
|
||||||
|
|
||||||
RenderObject *objects;
|
|
||||||
size_t objectsSize;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct QueueFamiliesBundle
|
|
||||||
{
|
|
||||||
uint32_t transfer = QUEUE_FAMILY_NO_VALUE;
|
|
||||||
uint32_t graphics = QUEUE_FAMILY_NO_VALUE;
|
|
||||||
uint32_t present = QUEUE_FAMILY_NO_VALUE;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct QueuesBundle
|
|
||||||
{
|
|
||||||
VkQueue transfer;
|
|
||||||
VkQueue graphics;
|
|
||||||
VkQueue present;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct DrawConfig
|
|
||||||
{
|
|
||||||
VkCommandBufferBeginInfo commandBeginConfig {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.flags = 0,
|
|
||||||
.pInheritanceInfo = nullptr
|
|
||||||
};
|
|
||||||
|
|
||||||
VkClearValue clearColor {{{1.0f, 1.0f, 1.0f, 1.0f}}};
|
|
||||||
|
|
||||||
VkRenderPassBeginInfo renderPassBeginConfig {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.clearValueCount = 1,
|
|
||||||
.pClearValues = &clearColor
|
|
||||||
};
|
|
||||||
|
|
||||||
VkPipelineStageFlags waitImageStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
|
||||||
|
|
||||||
VkSubmitInfo submitConfig {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.waitSemaphoreCount = 1,
|
|
||||||
.pWaitDstStageMask = &waitImageStage,
|
|
||||||
.commandBufferCount = 1,
|
|
||||||
.signalSemaphoreCount = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
VkPresentInfoKHR presentConfig {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.waitSemaphoreCount = 1,
|
|
||||||
.swapchainCount = 1,
|
|
||||||
.pResults = nullptr
|
|
||||||
};
|
|
||||||
|
|
||||||
VkVertexInputBindingDescription vertexBindingConfig {
|
|
||||||
.binding = 0,
|
|
||||||
.stride = sizeof(GPU_Vertex),
|
|
||||||
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SurfaceInfo
|
|
||||||
{
|
|
||||||
VkSurfaceCapabilitiesKHR capabilities;
|
|
||||||
std::vector<VkSurfaceFormatKHR> availableFormats;
|
|
||||||
std::vector<VkPresentModeKHR> availablePresentModes;
|
|
||||||
|
|
||||||
VkSurfaceFormatKHR format;
|
|
||||||
VkPresentModeKHR presentMode;
|
|
||||||
VkExtent2D extent;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Renderer
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Renderer(GLFWwindow *window, const AssetMaterial& baseMaterial, const size_t &vertexBufferSize, const size_t &indexBufferSize);
|
|
||||||
~Renderer();
|
|
||||||
|
|
||||||
void Start();
|
|
||||||
void Shutdown();
|
|
||||||
|
|
||||||
bool GetThreadStatus();
|
|
||||||
bool GetDrawStatus();
|
|
||||||
|
|
||||||
void RegisterObjects(RenderObject* objects, size_t size);
|
|
||||||
void ResizeWindow(int width, int height);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::atomic<bool> isRunning;
|
|
||||||
std::atomic<bool> isDrawing;
|
|
||||||
std::atomic<int> screenWidth, screenHeight;
|
|
||||||
|
|
||||||
std::stop_token *stoken;
|
|
||||||
std::jthread renderThread;
|
|
||||||
boost::lockfree::spsc_queue<RenderCommand, boost::lockfree::capacity<512>> commands;
|
|
||||||
|
|
||||||
GLFWwindow *window;
|
|
||||||
|
|
||||||
VkInstance vulkan;
|
|
||||||
VkSurfaceKHR surface;
|
|
||||||
VkPhysicalDevice gpu;
|
|
||||||
VkDevice device;
|
|
||||||
VkSwapchainKHR swapchain;
|
|
||||||
VkRenderPass baseRenderPass;
|
|
||||||
VkCommandPool graphicsCommandPool = nullptr;
|
|
||||||
VkCommandPool transferCommandPool = nullptr;
|
|
||||||
VkDeviceMemory worldVerticesMemory;
|
|
||||||
VkDeviceMemory worldIndicesMemory;
|
|
||||||
VkDeviceMemory stagingWorldVerticesMemory;
|
|
||||||
VkDeviceMemory stagingWorldIndicesMemory;
|
|
||||||
VkDeviceMemory uiVerticesMemory;
|
|
||||||
VkDeviceMemory uiIndicesMemory;
|
|
||||||
VkBuffer worldVertices;
|
|
||||||
VkBuffer worldIndices;
|
|
||||||
VkBuffer stagingWorldVertices;
|
|
||||||
VkBuffer stagingWorldIndices;
|
|
||||||
VkBuffer uiVertices;
|
|
||||||
VkBuffer uiIndices;
|
|
||||||
std::vector<VkDeviceMemory> worldUniformsMemory;
|
|
||||||
std::vector<VkBuffer> worldUniforms;
|
|
||||||
std::vector<VkDeviceMemory> uiUniformsMemory;
|
|
||||||
std::vector<VkBuffer> uiUniforms;
|
|
||||||
std::vector<VkCommandBuffer> graphicsCommandBuffers;
|
|
||||||
std::vector<VkCommandBuffer> transferCommandBuffers;
|
|
||||||
std::vector<VkImage> frames;
|
|
||||||
std::vector<VkImageView> frameViews;
|
|
||||||
std::vector<VkFramebuffer> baseFrameBuffers;
|
|
||||||
std::vector<VkSemaphore> imageAvailable;
|
|
||||||
std::vector<VkSemaphore> renderFinished;
|
|
||||||
std::vector<VkFence> inFlightFences;
|
|
||||||
std::vector<VkFence> imagesInFlight;
|
|
||||||
|
|
||||||
SurfaceInfo surfaceInfo;
|
|
||||||
QueueFamiliesBundle queueFamilies;
|
|
||||||
QueuesBundle queues;
|
|
||||||
DrawConfig drawConfig;
|
|
||||||
PipelineFactory *pipelineFactory;
|
|
||||||
PipelineBinding pipelineBinding;
|
|
||||||
size_t currentFrame = 0;
|
|
||||||
|
|
||||||
GPU_Buffer<GPU_Vertex> worldVerticesBinded;
|
|
||||||
GPU_Buffer<INDICES_SIZE> worldIndicesBinded;
|
|
||||||
GPU_Buffer<GPU_Vertex> uiVerticesBinded;
|
|
||||||
GPU_Buffer<INDICES_SIZE> uiIndicesBinded;
|
|
||||||
|
|
||||||
const float DEFAULT_QUEUE_PRIORITY = 1.0f;
|
|
||||||
const AssetMaterial &baseMaterial;
|
|
||||||
const size_t MAX_FRAMES_IN_FLIGHT = 2;
|
|
||||||
const size_t VERTEX_BUFFER_SIZE;
|
|
||||||
const size_t INDEX_BUFFER_SIZE;
|
|
||||||
|
|
||||||
std::set<RenderObject> objects;
|
|
||||||
|
|
||||||
//Rml::Context *uiContext;
|
|
||||||
|
|
||||||
void InitVulkan();
|
|
||||||
void SetupDevice();
|
|
||||||
void SetupSwapchain();
|
|
||||||
void RecreateSwapchain();
|
|
||||||
void ReleaseSwapchain();
|
|
||||||
void SetupRenderPasses();
|
|
||||||
void SetupPipelines();
|
|
||||||
void SetupObjectsBuffers();
|
|
||||||
void SetupRenderBuffers();
|
|
||||||
void SetupSync();
|
|
||||||
|
|
||||||
void Draw();
|
|
||||||
void CopyBuffer(VkBuffer src, size_t offset, VkBuffer dst, VkDeviceSize size);
|
|
||||||
|
|
||||||
void Threading();
|
|
||||||
void Request(const RenderCommand &command);
|
|
||||||
void Request(const RenderCommand::Type &type);
|
|
||||||
void Init();
|
|
||||||
void Loop();
|
|
||||||
void ProcessCommand(const RenderCommand &command);
|
|
||||||
void Release();
|
|
||||||
|
|
||||||
};
|
|
||||||
@ -1,29 +0,0 @@
|
|||||||
#include "GPU_Types/GPU_BaseTypes.hpp"
|
|
||||||
#include "GPU_Types/GPU_RenderUBO.hpp"
|
|
||||||
|
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
|
||||||
|
|
||||||
std::array<VkVertexInputAttributeDescription, 2> GPU_Vertex::GetAttributes()
|
|
||||||
{
|
|
||||||
VkVertexInputAttributeDescription posAttribute = {
|
|
||||||
.location = 0,
|
|
||||||
.binding = 0,
|
|
||||||
.format = ATTRIBUTE_FORMAT_VEC2,
|
|
||||||
.offset = offsetof(GPU_Vertex, pos)
|
|
||||||
};
|
|
||||||
VkVertexInputAttributeDescription colorAttribute = {
|
|
||||||
.location = 1,
|
|
||||||
.binding = 0,
|
|
||||||
.format = ATTRIBUTE_FORMAT_VEC3,
|
|
||||||
.offset = offsetof(GPU_Vertex, color)
|
|
||||||
};
|
|
||||||
|
|
||||||
return {posAttribute, colorAttribute};
|
|
||||||
}
|
|
||||||
|
|
||||||
void GPU_TranformUBO::Update(const GPU_Transform &transform)
|
|
||||||
{
|
|
||||||
model = glm::mat4(1.0f);
|
|
||||||
model = glm::translate(model, transform.pos);
|
|
||||||
model = glm::scale(model, transform.scale);
|
|
||||||
}
|
|
||||||
@ -1,314 +0,0 @@
|
|||||||
#include "PipelineFactory.hpp"
|
|
||||||
#include "Engine.hpp"
|
|
||||||
#include "Logger.h"
|
|
||||||
|
|
||||||
PipelineConfig PipelineConfig::Copy() const
|
|
||||||
{
|
|
||||||
PipelineConfig copy = *this;
|
|
||||||
|
|
||||||
copy.viewportStateConfig.pViewports = ©.defaultViewport;
|
|
||||||
copy.viewportStateConfig.pScissors = ©.defaultScissors;
|
|
||||||
copy.dynamicStateConfig.pDynamicStates = copy.dynamicStates.data();
|
|
||||||
copy.colorBlendConfig.pAttachments = copy.colorBlendAttachmentConfigs.data();
|
|
||||||
copy.uniformsConfig.pBindings = copy.uniforms.data();
|
|
||||||
copy.pipelineConfig.pVertexInputState = ©.vertexInputConfig;
|
|
||||||
copy.pipelineConfig.pInputAssemblyState = ©.inputAssemblyConfig;
|
|
||||||
copy.pipelineConfig.pViewportState = ©.viewportStateConfig;
|
|
||||||
copy.pipelineConfig.pRasterizationState = ©.rasterizerConfig;
|
|
||||||
copy.pipelineConfig.pMultisampleState = ©.multisamplingConfig;
|
|
||||||
copy.pipelineConfig.pDepthStencilState = nullptr;
|
|
||||||
copy.pipelineConfig.pColorBlendState = ©.colorBlendConfig;
|
|
||||||
copy.pipelineConfig.pDynamicState = ©.dynamicStateConfig;
|
|
||||||
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
PipelineFactory::PipelineFactory(const PipelineBinding &binding) :
|
|
||||||
device(*binding.device),
|
|
||||||
surfaceExtent(*binding.surfaceExtent),
|
|
||||||
vertexBindingConfig(*binding.vertexBindingConfig)
|
|
||||||
{
|
|
||||||
this->binding = binding;
|
|
||||||
|
|
||||||
basePipelineConfig.dynamicStates.push_back(VK_DYNAMIC_STATE_VIEWPORT);
|
|
||||||
basePipelineConfig.dynamicStates.push_back(VK_DYNAMIC_STATE_SCISSOR);
|
|
||||||
|
|
||||||
basePipelineConfig.colorBlendAttachmentConfigs.push_back({
|
|
||||||
.blendEnable = VK_TRUE,
|
|
||||||
.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA,
|
|
||||||
.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
|
|
||||||
.colorBlendOp = VK_BLEND_OP_ADD,
|
|
||||||
.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
|
|
||||||
.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO,
|
|
||||||
.alphaBlendOp = VK_BLEND_OP_ADD,
|
|
||||||
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
|
|
||||||
});
|
|
||||||
|
|
||||||
basePipelineConfig.uniforms.push_back({
|
|
||||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
|
||||||
.descriptorCount = 1,
|
|
||||||
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
|
||||||
.pImmutableSamplers = nullptr
|
|
||||||
}); // GPU_GlobalUBO
|
|
||||||
|
|
||||||
basePipelineConfig.uniforms.push_back({
|
|
||||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
|
||||||
.descriptorCount = 1,
|
|
||||||
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
|
||||||
.pImmutableSamplers = nullptr
|
|
||||||
}); // GPU_TransformUBO
|
|
||||||
|
|
||||||
basePipelineConfig.vertexInputConfig = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.vertexBindingDescriptionCount = 1,
|
|
||||||
.pVertexBindingDescriptions = &vertexBindingConfig,
|
|
||||||
.vertexAttributeDescriptionCount = binding.vertexAttributesCount,
|
|
||||||
.pVertexAttributeDescriptions = binding.vertexAttributesConfig
|
|
||||||
};
|
|
||||||
|
|
||||||
basePipelineConfig.inputAssemblyConfig = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
|
|
||||||
.primitiveRestartEnable = VK_FALSE
|
|
||||||
};
|
|
||||||
|
|
||||||
basePipelineConfig.rasterizerConfig = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.depthClampEnable = VK_FALSE,
|
|
||||||
.rasterizerDiscardEnable = VK_FALSE,
|
|
||||||
.polygonMode = VK_POLYGON_MODE_FILL,
|
|
||||||
.cullMode = VK_CULL_MODE_NONE,
|
|
||||||
.depthBiasEnable = VK_FALSE,
|
|
||||||
.lineWidth = 1.0f,
|
|
||||||
};
|
|
||||||
|
|
||||||
basePipelineConfig.multisamplingConfig = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
|
|
||||||
.sampleShadingEnable = VK_FALSE,
|
|
||||||
};
|
|
||||||
|
|
||||||
basePipelineConfig.depthStencilConfig = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
};
|
|
||||||
|
|
||||||
basePipelineConfig.dynamicStateConfig = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.dynamicStateCount = static_cast<uint32_t>(basePipelineConfig.dynamicStates.size()),
|
|
||||||
.pDynamicStates = basePipelineConfig.dynamicStates.data()
|
|
||||||
};
|
|
||||||
|
|
||||||
basePipelineConfig.uniformsConfig = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
|
||||||
.bindingCount = static_cast<uint32_t>(basePipelineConfig.uniforms.size()),
|
|
||||||
.pBindings = basePipelineConfig.uniforms.data()
|
|
||||||
};
|
|
||||||
|
|
||||||
basePipelineConfig.pipelineLayoutConfig = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.setLayoutCount = 1,
|
|
||||||
.pushConstantRangeCount = 0,
|
|
||||||
.pPushConstantRanges = nullptr
|
|
||||||
};
|
|
||||||
|
|
||||||
basePipelineConfig.defaultViewport = {
|
|
||||||
.x = 0.0f,
|
|
||||||
.y = 0.0f,
|
|
||||||
.width = static_cast<float>(surfaceExtent.width),
|
|
||||||
.height = static_cast<float>(surfaceExtent.height),
|
|
||||||
.minDepth = 0.0f,
|
|
||||||
.maxDepth = 1.0f
|
|
||||||
};
|
|
||||||
|
|
||||||
basePipelineConfig.defaultScissors = {
|
|
||||||
.offset = {.x = 0, .y = 0},
|
|
||||||
.extent = surfaceExtent
|
|
||||||
};
|
|
||||||
|
|
||||||
basePipelineConfig.viewportStateConfig = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.viewportCount = 1,
|
|
||||||
.pViewports = &basePipelineConfig.defaultViewport,
|
|
||||||
.scissorCount = 1,
|
|
||||||
.pScissors = &basePipelineConfig.defaultScissors
|
|
||||||
};
|
|
||||||
|
|
||||||
basePipelineConfig.colorBlendConfig = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.logicOpEnable = VK_FALSE,
|
|
||||||
.attachmentCount = static_cast<uint32_t>(basePipelineConfig.colorBlendAttachmentConfigs.size()),
|
|
||||||
.pAttachments = basePipelineConfig.colorBlendAttachmentConfigs.data(),
|
|
||||||
};
|
|
||||||
|
|
||||||
basePipelineConfig.pipelineConfig = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.pVertexInputState = &basePipelineConfig.vertexInputConfig,
|
|
||||||
.pInputAssemblyState = &basePipelineConfig.inputAssemblyConfig,
|
|
||||||
.pViewportState = &basePipelineConfig.viewportStateConfig,
|
|
||||||
.pRasterizationState = &basePipelineConfig.rasterizerConfig,
|
|
||||||
.pMultisampleState = &basePipelineConfig.multisamplingConfig,
|
|
||||||
.pDepthStencilState = nullptr,
|
|
||||||
.pColorBlendState = &basePipelineConfig.colorBlendConfig,
|
|
||||||
.pDynamicState = &basePipelineConfig.dynamicStateConfig,
|
|
||||||
.basePipelineHandle = VK_NULL_HANDLE,
|
|
||||||
.basePipelineIndex = -1
|
|
||||||
};
|
|
||||||
|
|
||||||
LOG(INFO, "Creating base material pipeline...");
|
|
||||||
Create(*binding.baseMaterial, *binding.baseRenderPass, PIPELINE_CREATE_NEW);
|
|
||||||
LOG(INFO, "Base material pipeline created");
|
|
||||||
}
|
|
||||||
|
|
||||||
Pipeline& PipelineFactory::Get(const AssetMaterial &material)
|
|
||||||
{
|
|
||||||
if (pipelines.contains(&material))
|
|
||||||
return pipelines[&material];
|
|
||||||
else return basePipeline;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PipelineFactory::Create(const AssetMaterial &material, const VkRenderPass &renderPass, const uint32_t &flags)
|
|
||||||
{
|
|
||||||
VkResult vkResult;
|
|
||||||
|
|
||||||
Pipeline newPipeline {};
|
|
||||||
Pipeline *result = &basePipeline;
|
|
||||||
|
|
||||||
PipelineConfig newConfig;
|
|
||||||
PipelineConfig *config = &basePipelineConfig;
|
|
||||||
|
|
||||||
if (flags & PIPELINE_CREATE_DERIVED)
|
|
||||||
{
|
|
||||||
newConfig = basePipelineConfig.Copy();
|
|
||||||
config = &newConfig;
|
|
||||||
|
|
||||||
result = &newPipeline;
|
|
||||||
config->pipelineConfig.basePipelineHandle = basePipeline.instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Configure shaders
|
|
||||||
AssetHandle shaderHandle;
|
|
||||||
AssetShader *shader;
|
|
||||||
VkShaderModuleCreateInfo shaderModuleCreateConfig;
|
|
||||||
std::vector<VkPipelineShaderStageCreateInfo> stagesConfigs;
|
|
||||||
|
|
||||||
stagesConfigs.reserve(3);
|
|
||||||
|
|
||||||
// Vertex
|
|
||||||
VkShaderModule vertexModule;
|
|
||||||
shaderHandle = Engine::assetManager->Find(material.vertexShaderAssetID);
|
|
||||||
shader = &Engine::assetManager->Get<AssetShader>(shaderHandle);
|
|
||||||
shaderModuleCreateConfig = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.codeSize = shader->size,
|
|
||||||
.pCode = shader->content
|
|
||||||
};
|
|
||||||
vkResult = vkCreateShaderModule(device, &shaderModuleCreateConfig, nullptr, &vertexModule);
|
|
||||||
if (vkResult != VK_SUCCESS)
|
|
||||||
LOG(ERROR, "Failed to create vertex shader module [Asset ID: %d]. Code: %d", shaderHandle.id, vkResult);
|
|
||||||
stagesConfigs.push_back({
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.stage = VK_SHADER_STAGE_VERTEX_BIT,
|
|
||||||
.module = vertexModule,
|
|
||||||
.pName = "main",
|
|
||||||
.pSpecializationInfo = nullptr
|
|
||||||
});
|
|
||||||
|
|
||||||
VkDescriptorSetLayoutBinding baseBinding {
|
|
||||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
|
||||||
.descriptorCount = 1,
|
|
||||||
.pImmutableSamplers = nullptr
|
|
||||||
};
|
|
||||||
baseBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
|
|
||||||
|
|
||||||
// Fragment
|
|
||||||
VkShaderModule fragmentModule;
|
|
||||||
shaderHandle = Engine::assetManager->Find(material.fragmentShaderAssetID);
|
|
||||||
shader = &Engine::assetManager->Get<AssetShader>(shaderHandle);
|
|
||||||
shaderModuleCreateConfig = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.codeSize = shader->size,
|
|
||||||
.pCode = shader->content
|
|
||||||
};
|
|
||||||
vkResult = vkCreateShaderModule(device, &shaderModuleCreateConfig, nullptr, &fragmentModule);
|
|
||||||
if (vkResult != VK_SUCCESS)
|
|
||||||
LOG(ERROR, "Failed to create fragment shader module [Asset ID: %d]. Code: %d", shaderHandle.id, vkResult);
|
|
||||||
stagesConfigs.push_back({
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.stage = VK_SHADER_STAGE_FRAGMENT_BIT,
|
|
||||||
.module = fragmentModule,
|
|
||||||
.pName = "main",
|
|
||||||
.pSpecializationInfo = nullptr
|
|
||||||
});
|
|
||||||
|
|
||||||
baseBinding.binding = 0;
|
|
||||||
baseBinding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
vkResult = vkCreateDescriptorSetLayout(device, &config->uniformsConfig, nullptr, &result->uniformsLayout);
|
|
||||||
if (vkResult != VK_SUCCESS)
|
|
||||||
LOG(CRITICAL, "Failed to create uniforms layout");
|
|
||||||
config->pipelineLayoutConfig.pSetLayouts = &result->uniformsLayout;
|
|
||||||
|
|
||||||
vkResult = vkCreatePipelineLayout(
|
|
||||||
device,
|
|
||||||
&config->pipelineLayoutConfig,
|
|
||||||
nullptr,
|
|
||||||
&result->layout
|
|
||||||
);
|
|
||||||
if (vkResult != VK_SUCCESS)
|
|
||||||
LOG(CRITICAL, "Failed to create pipeline layout");
|
|
||||||
config->pipelineConfig.layout = result->layout;
|
|
||||||
|
|
||||||
config->pipelineConfig.stageCount = static_cast<uint32_t>(stagesConfigs.size());
|
|
||||||
config->pipelineConfig.pStages = stagesConfigs.data();
|
|
||||||
config->pipelineConfig.renderPass = renderPass;
|
|
||||||
config->pipelineConfig.subpass = material.renderStage;
|
|
||||||
|
|
||||||
vkResult = vkCreateGraphicsPipelines(
|
|
||||||
device,
|
|
||||||
VK_NULL_HANDLE,
|
|
||||||
1,
|
|
||||||
&config->pipelineConfig,
|
|
||||||
nullptr,
|
|
||||||
&result->instance
|
|
||||||
);
|
|
||||||
if (vkResult != VK_SUCCESS)
|
|
||||||
LOG(CRITICAL, "Failed to create pipeline");
|
|
||||||
|
|
||||||
if (flags & PIPELINE_CREATE_DERIVED)
|
|
||||||
pipelines[&material] = newPipeline;
|
|
||||||
|
|
||||||
result->viewport = config->defaultViewport;
|
|
||||||
result->scissors = config->defaultScissors;
|
|
||||||
|
|
||||||
vkDestroyShaderModule(device, vertexModule, nullptr);
|
|
||||||
vkDestroyShaderModule(device, fragmentModule, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
PipelineFactory::~PipelineFactory()
|
|
||||||
{
|
|
||||||
vkDestroyPipeline(device, basePipeline.instance, nullptr);
|
|
||||||
vkDestroyPipelineLayout(device, basePipeline.layout, nullptr);
|
|
||||||
vkDestroyDescriptorSetLayout(device, basePipeline.uniformsLayout, nullptr);
|
|
||||||
for (auto &item : pipelines)
|
|
||||||
{
|
|
||||||
vkDestroyPipeline(device, item.second.instance, nullptr);
|
|
||||||
vkDestroyPipelineLayout(device, item.second.layout, nullptr);
|
|
||||||
vkDestroyDescriptorSetLayout(device, item.second.uniformsLayout, nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,97 +0,0 @@
|
|||||||
#include "Logger.h"
|
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
|
|
||||||
#include "compile_config.hpp"
|
|
||||||
#include "Engine.hpp"
|
|
||||||
|
|
||||||
IP7_Trace* Logger::trace;
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
// Setup P7 logger
|
|
||||||
IP7_Client *p7client = P7_Create_Client(P7_SINK);
|
|
||||||
P7_Set_Crash_Handler();
|
|
||||||
Logger::trace = P7_Create_Trace(p7client, L"TC 1");
|
|
||||||
Logger::trace->Register_Thread(L"Main", 0);
|
|
||||||
|
|
||||||
LOG(INFO, "Etredia Empires, v%d.%d.%d", MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION);
|
|
||||||
|
|
||||||
// Setup GLFW
|
|
||||||
glfwInit();
|
|
||||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
|
||||||
|
|
||||||
GLFWwindow *window = glfwCreateWindow(800, 600, "Etredia Empires", nullptr, nullptr);
|
|
||||||
|
|
||||||
if (!window)
|
|
||||||
LOG(CRITICAL, "GLFW Window failed");
|
|
||||||
else LOG(INFO, "GLFW Window created");
|
|
||||||
|
|
||||||
// Setup assets
|
|
||||||
AssetManager assetManager;
|
|
||||||
assetManager.Start();
|
|
||||||
assetManager.LoadShaders();
|
|
||||||
|
|
||||||
// Setup Renderer
|
|
||||||
assetManager.LoadAsync(AssetInfo::MATERIAL, "assets/materials/helloworld.mat");
|
|
||||||
AssetHandle baseMaterialHandle = assetManager.Find("assets/materials/helloworld.mat");
|
|
||||||
AssetMaterial baseMaterial = assetManager.Get<AssetMaterial>(baseMaterialHandle);
|
|
||||||
Renderer renderer(window, baseMaterial, 1000000, 1000000); //TODO: buffer sizes
|
|
||||||
renderer.Start();
|
|
||||||
|
|
||||||
//Setup Engine
|
|
||||||
Engine::assetManager = &assetManager;
|
|
||||||
Engine::renderer = &renderer;
|
|
||||||
|
|
||||||
glfwSetFramebufferSizeCallback(window, [](GLFWwindow *window, int width, int height) {
|
|
||||||
Engine::renderer->ResizeWindow(width, height);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Test render obj
|
|
||||||
RenderObject triangle {
|
|
||||||
.transforms = {{.pos = {0.0f, 0.0f, 0.0f}}},
|
|
||||||
.mesh = {
|
|
||||||
.vertices = {
|
|
||||||
{.pos = {-0.5f, -0.5f}, .color = {0.0f, 0.0f, 0.0f}},
|
|
||||||
{.pos = {0.0f, 0.5f}, .color = {0.0f, 0.0f, 0.0f}},
|
|
||||||
{.pos = {-1.0f, 0.5f}, .color = {0.0f, 0.0f, 0.0f}}
|
|
||||||
},
|
|
||||||
.indices = {0, 1, 2}
|
|
||||||
},
|
|
||||||
|
|
||||||
.material = baseMaterial,
|
|
||||||
};
|
|
||||||
RenderObject rect {
|
|
||||||
.transforms = {{.pos = {0.0f, 0.0f, 0.0f}}},
|
|
||||||
.mesh = {
|
|
||||||
.vertices = {
|
|
||||||
{.pos = {-0.5f, -0.5f}, .color = {1.0f, 0.0f, 0.0f}},
|
|
||||||
{.pos = {0.5f, -0.5f}, .color = {0.0f, 1.0f, 0.0f}},
|
|
||||||
{.pos = {0.5f, 0.5f}, .color = {0.0f, 0.0f, 1.0f}},
|
|
||||||
{.pos = {-0.5f, 0.5f}, .color = {0.0f, 0.0f, 0.0f}}
|
|
||||||
},
|
|
||||||
.indices = { 0, 1, 2, 2, 3, 0}
|
|
||||||
},
|
|
||||||
|
|
||||||
.material = baseMaterial,
|
|
||||||
};
|
|
||||||
RenderObject objs[] = {triangle, rect};
|
|
||||||
renderer.RegisterObjects(objs, 2);
|
|
||||||
|
|
||||||
// Process GLFW events
|
|
||||||
while(!glfwWindowShouldClose(window))
|
|
||||||
{
|
|
||||||
glfwPollEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free memory
|
|
||||||
LOG(INFO, "Exit...");
|
|
||||||
renderer.Shutdown(); while(renderer.GetThreadStatus());
|
|
||||||
assetManager.Shutdown(); while(assetManager.isRunning.load());
|
|
||||||
glfwDestroyWindow(window);
|
|
||||||
glfwTerminate();
|
|
||||||
Logger::trace->Unregister_Thread(0);
|
|
||||||
Logger::trace->Release();
|
|
||||||
p7client->Release();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -16,7 +16,7 @@ find_package(xxHash CONFIG REQUIRED)
|
|||||||
add_executable(${PROJECT_NAME} compile_materials.cpp)
|
add_executable(${PROJECT_NAME} compile_materials.cpp)
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE nlohmann_json::nlohmann_json)
|
target_link_libraries(${PROJECT_NAME} PRIVATE nlohmann_json::nlohmann_json)
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE xxHash::xxhash)
|
target_link_libraries(${PROJECT_NAME} PRIVATE xxHash::xxhash)
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}/frontend/include/)
|
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_SOURCE_DIR}/engine/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)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user