This commit is contained in:
legatt 2026-01-14 15:26:09 +03:00
parent fd6437a94b
commit 945cf4b1cc
11 changed files with 230 additions and 107 deletions

Binary file not shown.

View File

@ -13,11 +13,12 @@ project (EEfrontend)
# List sources # List sources
set(HEADERS "Engine.hpp" "Renderer.hpp" "FileSystem.hpp" "compile_config.hpp" "AssetManager.hpp" "AssetData.hpp" "PipelineFactory.hpp") file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS
set(SOURCES "main.cpp" "Engine.cpp" "Renderer.cpp" "FileSystem.cpp" "AssetManager.cpp" "AssetData.cpp" "PipelineFactory.cpp") "src/*.cpp"
"src/*.c"
list(TRANSFORM HEADERS PREPEND "include/") "include/*.hpp"
list(TRANSFORM SOURCES PREPEND "src/") "include/*.h"
)
# Find dependencies # Find dependencies
@ -30,7 +31,7 @@ find_package(RmlUi CONFIG REQUIRED)
# Link library # Link library
add_executable(${PROJECT_NAME} ${HEADERS} ${SOURCES}) add_executable(${PROJECT_NAME} ${SOURCES})
target_link_libraries(${PROJECT_NAME} PUBLIC utils) target_link_libraries(${PROJECT_NAME} PUBLIC utils)

View File

@ -29,4 +29,10 @@ struct AssetMaterial : AssetData
uint32_t fragmentShaderAssetID; uint32_t fragmentShaderAssetID;
uint32_t renderType; uint32_t renderType;
uint32_t renderStage; uint32_t renderStage;
// Vertex shader params
// <param id:value>
// Fragment shader params
// <param id:value>
}; };

View File

@ -0,0 +1,84 @@
#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
// }

View File

@ -0,0 +1,18 @@
#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);
};

View File

@ -39,6 +39,10 @@ struct PipelineConfig
VkRect2D defaultScissors; VkRect2D defaultScissors;
std::vector<VkDynamicState> dynamicStates; std::vector<VkDynamicState> dynamicStates;
std::vector<VkDescriptorSetLayoutBinding> uniforms;
int vertexBindingsCount, fragmentBindingsCount;
VkDescriptorSetLayoutCreateInfo uniformsConfig;
VkGraphicsPipelineCreateInfo pipelineConfig; VkGraphicsPipelineCreateInfo pipelineConfig;
PipelineConfig Copy() const; PipelineConfig Copy() const;
@ -48,6 +52,7 @@ struct Pipeline
{ {
VkPipeline instance; VkPipeline instance;
VkPipelineLayout layout; VkPipelineLayout layout;
VkDescriptorSetLayout uniformsLayout;
VkViewport viewport; VkViewport viewport;
VkRect2D scissors; VkRect2D scissors;
}; };

View File

@ -2,14 +2,14 @@
#include <thread> #include <thread>
#include <atomic> #include <atomic>
#include <cstdint> #include <cstdint>
#include <array>
#include <vector> #include <vector>
#include <set> #include <set>
#include <Boost/lockfree/spsc_queue.hpp> #include <Boost/lockfree/spsc_queue.hpp>
#define GLFW_INCLUDE_VULKAN #define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include "GPU_Types/GPU_BaseTypes.hpp"
#include "PipelineFactory.hpp" #include "PipelineFactory.hpp"
@ -19,10 +19,6 @@
#define VALIDATION_LAYER #define VALIDATION_LAYER
#endif #endif
#define ATTRIBUTE_FORMAT_VEC2 VK_FORMAT_R32G32_SFLOAT
#define ATTRIBUTE_FORMAT_VEC3 VK_FORMAT_R32G32B32_SFLOAT
#define ATTRIBUTE_FORMAT_VEC4 VK_FORMAT_R32G32B32A32_SFLOAT
// GPU properties priority for selection // GPU properties priority for selection
#define GPU_DISCRETE_PRIORITY 1000 #define GPU_DISCRETE_PRIORITY 1000
#define GPU_GRAPHICS_WITH_PRESENT_PRIORITY 500 #define GPU_GRAPHICS_WITH_PRESENT_PRIORITY 500
@ -36,84 +32,6 @@
#define INDICES_SIZE uint16_t #define INDICES_SIZE uint16_t
#define INDICES_SIZE_VK VK_INDEX_TYPE_UINT16 #define INDICES_SIZE_VK VK_INDEX_TYPE_UINT16
struct Transform
{
float x = 0.0f, y = 0.0f;
float scaleX = 1.0f, scaleY = 1.0f, scaleZ = 1.0f;
};
struct GPU_Vertex
{
glm::vec2 pos;
glm::vec3 color;
static std::array<VkVertexInputAttributeDescription, 2> 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};
}
};
struct GPU_BufferSlot
{
size_t position;
size_t size;
};
//TODO: move methods definition to the end of file
template<typename T> struct GPU_Buffer
{
T *data;
size_t size;
const size_t ELEMENT_SIZE;
std::vector<GPU_BufferSlot> freeSlots;
GPU_Buffer() : ELEMENT_SIZE(sizeof(T)) {freeSlots.push_back({.position = 0, .size = size});}
GPU_BufferSlot* FindFreeSlot(size_t size)
{
for (auto i = freeSlots.rbegin(); i != freeSlots.rend(); i++)
{
if (i->size >= size)
return &(*i);
}
return nullptr;
}
size_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;
}
// void Clear(GPU_BufferSlot range)
// {
// freeSlots.push_back(range);
// //TODO: insert sorted by pos and combine intersections
// }
};
struct Mesh struct Mesh
{ {
size_t verticesBufferPosition = 0; size_t verticesBufferPosition = 0;
@ -122,19 +40,27 @@ struct Mesh
std::vector<INDICES_SIZE> indices; std::vector<INDICES_SIZE> indices;
}; };
struct MaterialParams
{
VkDescriptorSet descriptors;
//TODO: push-constants
void Set(const char** param, const char** property = nullptr);
};
struct RenderObject struct RenderObject
{ {
uint32_t engineId = UINT32_MAX; uint32_t engineId = UINT32_MAX;
// Multiple transforms for batching // Multiple transforms for batching
std::vector<Transform> transforms; std::vector<GPU_Transform> transforms;
uint8_t depth = 0; uint8_t depth = 0;
Mesh mesh; Mesh mesh;
bool isUI = false; bool isUI = false;
//TODO: texture //TODO: texture
AssetMaterial &material; AssetMaterial &material;
//TODO: materialParams (uniforms) MaterialParams materialParams;
}; };
bool operator < (const RenderObject& lhs, const RenderObject& rhs); bool operator < (const RenderObject& lhs, const RenderObject& rhs);
@ -268,6 +194,10 @@ private:
VkBuffer stagingWorldIndices; VkBuffer stagingWorldIndices;
VkBuffer uiVertices; VkBuffer uiVertices;
VkBuffer uiIndices; 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> graphicsCommandBuffers;
std::vector<VkCommandBuffer> transferCommandBuffers; std::vector<VkCommandBuffer> transferCommandBuffers;
std::vector<VkImage> frames; std::vector<VkImage> frames;

View File

@ -0,0 +1,29 @@
#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);
}

View File

@ -10,6 +10,7 @@ PipelineConfig PipelineConfig::Copy() const
copy.viewportStateConfig.pScissors = &copy.defaultScissors; copy.viewportStateConfig.pScissors = &copy.defaultScissors;
copy.dynamicStateConfig.pDynamicStates = copy.dynamicStates.data(); copy.dynamicStateConfig.pDynamicStates = copy.dynamicStates.data();
copy.colorBlendConfig.pAttachments = copy.colorBlendAttachmentConfigs.data(); copy.colorBlendConfig.pAttachments = copy.colorBlendAttachmentConfigs.data();
copy.uniformsConfig.pBindings = copy.uniforms.data();
copy.pipelineConfig.pVertexInputState = &copy.vertexInputConfig; copy.pipelineConfig.pVertexInputState = &copy.vertexInputConfig;
copy.pipelineConfig.pInputAssemblyState = &copy.inputAssemblyConfig; copy.pipelineConfig.pInputAssemblyState = &copy.inputAssemblyConfig;
copy.pipelineConfig.pViewportState = &copy.viewportStateConfig; copy.pipelineConfig.pViewportState = &copy.viewportStateConfig;
@ -43,6 +44,20 @@ PipelineFactory::PipelineFactory(const PipelineBinding &binding) :
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT .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 = { basePipelineConfig.vertexInputConfig = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
@ -89,11 +104,16 @@ PipelineFactory::PipelineFactory(const PipelineBinding &binding) :
.pDynamicStates = basePipelineConfig.dynamicStates.data() .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 = { basePipelineConfig.pipelineLayoutConfig = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
.setLayoutCount = 0, //TODO: vector .setLayoutCount = 1,
.pSetLayouts = nullptr,
.pushConstantRangeCount = 0, .pushConstantRangeCount = 0,
.pPushConstantRanges = nullptr .pPushConstantRanges = nullptr
}; };
@ -158,6 +178,8 @@ Pipeline& PipelineFactory::Get(const AssetMaterial &material)
void PipelineFactory::Create(const AssetMaterial &material, const VkRenderPass &renderPass, const uint32_t &flags) void PipelineFactory::Create(const AssetMaterial &material, const VkRenderPass &renderPass, const uint32_t &flags)
{ {
VkResult vkResult;
Pipeline newPipeline {}; Pipeline newPipeline {};
Pipeline *result = &basePipeline; Pipeline *result = &basePipeline;
@ -173,16 +195,6 @@ void PipelineFactory::Create(const AssetMaterial &material, const VkRenderPass &
config->pipelineConfig.basePipelineHandle = basePipeline.instance; config->pipelineConfig.basePipelineHandle = basePipeline.instance;
} }
VkResult vkResult = vkCreatePipelineLayout(
device,
&config->pipelineLayoutConfig,
nullptr,
&result->layout
);
if (vkResult != VK_SUCCESS)
LOG(CRITICAL, "Failed to create pipeline layout");
config->pipelineConfig.layout = result->layout;
// Configure shaders // Configure shaders
AssetHandle shaderHandle; AssetHandle shaderHandle;
AssetShader *shader; AssetShader *shader;
@ -213,6 +225,13 @@ void PipelineFactory::Create(const AssetMaterial &material, const VkRenderPass &
.pSpecializationInfo = nullptr .pSpecializationInfo = nullptr
}); });
VkDescriptorSetLayoutBinding baseBinding {
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = 1,
.pImmutableSamplers = nullptr
};
baseBinding.stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
// Fragment // Fragment
VkShaderModule fragmentModule; VkShaderModule fragmentModule;
shaderHandle = Engine::assetManager->Find(material.fragmentShaderAssetID); shaderHandle = Engine::assetManager->Find(material.fragmentShaderAssetID);
@ -235,6 +254,26 @@ void PipelineFactory::Create(const AssetMaterial &material, const VkRenderPass &
.pSpecializationInfo = nullptr .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.stageCount = static_cast<uint32_t>(stagesConfigs.size());
config->pipelineConfig.pStages = stagesConfigs.data(); config->pipelineConfig.pStages = stagesConfigs.data();
config->pipelineConfig.renderPass = renderPass; config->pipelineConfig.renderPass = renderPass;
@ -265,9 +304,11 @@ PipelineFactory::~PipelineFactory()
{ {
vkDestroyPipeline(device, basePipeline.instance, nullptr); vkDestroyPipeline(device, basePipeline.instance, nullptr);
vkDestroyPipelineLayout(device, basePipeline.layout, nullptr); vkDestroyPipelineLayout(device, basePipeline.layout, nullptr);
vkDestroyDescriptorSetLayout(device, basePipeline.uniformsLayout, nullptr);
for (auto &item : pipelines) for (auto &item : pipelines)
{ {
vkDestroyPipeline(device, item.second.instance, nullptr); vkDestroyPipeline(device, item.second.instance, nullptr);
vkDestroyPipelineLayout(device, item.second.layout, nullptr); vkDestroyPipelineLayout(device, item.second.layout, nullptr);
vkDestroyDescriptorSetLayout(device, item.second.uniformsLayout, nullptr);
} }
} }

View File

@ -48,7 +48,7 @@ int main(int argc, char **argv)
// Test render obj // Test render obj
RenderObject triangle { RenderObject triangle {
.transforms = {{.x = 0, .y = 0}}, .transforms = {{.pos = {0.0f, 0.0f, 0.0f}}},
.mesh = { .mesh = {
.vertices = { .vertices = {
{.pos = {-0.5f, -0.5f}, .color = {0.0f, 0.0f, 0.0f}}, {.pos = {-0.5f, -0.5f}, .color = {0.0f, 0.0f, 0.0f}},
@ -61,7 +61,7 @@ int main(int argc, char **argv)
.material = baseMaterial, .material = baseMaterial,
}; };
RenderObject rect { RenderObject rect {
.transforms = {{.x = 0, .y = 0}}, .transforms = {{.pos = {0.0f, 0.0f, 0.0f}}},
.mesh = { .mesh = {
.vertices = { .vertices = {
{.pos = {-0.5f, -0.5f}, .color = {1.0f, 0.0f, 0.0f}}, {.pos = {-0.5f, -0.5f}, .color = {1.0f, 0.0f, 0.0f}},

View File

@ -1,12 +1,21 @@
#version 450 #version 450
#extension GL_ARB_separate_shader_objects : enable #extension GL_ARB_separate_shader_objects : enable
layout(binding = 0) uniform Global {
mat4 view;
mat4 proj;
} global;
layout(binding = 1) uniform Transform {
mat4 model;
} transform;
layout(location = 0) in vec2 inPosition; layout(location = 0) in vec2 inPosition;
layout(location = 1) in vec3 inColor; layout(location = 1) in vec3 inColor;
layout(location = 0) out vec3 fragColor; layout(location = 0) out vec3 fragColor;
void main() { void main() {
gl_Position = vec4(inPosition, 0.0, 1.0); gl_Position = global.proj * global.view * transform.model * vec4(inPosition, 0.0, 1.0);
fragColor = inColor; fragColor = inColor;
} }