diff --git a/assets/shaders/helloworld.vert.spv b/assets/shaders/helloworld.vert.spv index 7d2aebb..4062a52 100644 Binary files a/assets/shaders/helloworld.vert.spv and b/assets/shaders/helloworld.vert.spv differ diff --git a/frontend/CMakeLists.txt b/frontend/CMakeLists.txt index f1146f3..eedab98 100644 --- a/frontend/CMakeLists.txt +++ b/frontend/CMakeLists.txt @@ -13,11 +13,12 @@ project (EEfrontend) # List sources -set(HEADERS "Engine.hpp" "Renderer.hpp" "FileSystem.hpp" "compile_config.hpp" "AssetManager.hpp" "AssetData.hpp" "PipelineFactory.hpp") -set(SOURCES "main.cpp" "Engine.cpp" "Renderer.cpp" "FileSystem.cpp" "AssetManager.cpp" "AssetData.cpp" "PipelineFactory.cpp") - -list(TRANSFORM HEADERS PREPEND "include/") -list(TRANSFORM SOURCES PREPEND "src/") +file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS + "src/*.cpp" + "src/*.c" + "include/*.hpp" + "include/*.h" +) # Find dependencies @@ -30,7 +31,7 @@ find_package(RmlUi CONFIG REQUIRED) # Link library -add_executable(${PROJECT_NAME} ${HEADERS} ${SOURCES}) +add_executable(${PROJECT_NAME} ${SOURCES}) target_link_libraries(${PROJECT_NAME} PUBLIC utils) diff --git a/frontend/include/AssetData.hpp b/frontend/include/AssetData.hpp index bf4f427..32886f4 100644 --- a/frontend/include/AssetData.hpp +++ b/frontend/include/AssetData.hpp @@ -29,4 +29,10 @@ struct AssetMaterial : AssetData uint32_t fragmentShaderAssetID; uint32_t renderType; uint32_t renderStage; + + // Vertex shader params + // + + // Fragment shader params + // }; \ No newline at end of file diff --git a/frontend/include/GPU_Types/GPU_BaseTypes.hpp b/frontend/include/GPU_Types/GPU_BaseTypes.hpp new file mode 100644 index 0000000..7866bdc --- /dev/null +++ b/frontend/include/GPU_Types/GPU_BaseTypes.hpp @@ -0,0 +1,84 @@ +#pragma once + +#include +#include +#include +#include + +#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 GetAttributes(); +}; + +struct GPU_BufferSlot +{ + size_t position; + size_t size; +}; + +template struct GPU_Buffer +{ + T *data; + size_t size; + const size_t ELEMENT_SIZE; + std::vector 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 GPU_Buffer::GPU_Buffer() : ELEMENT_SIZE(sizeof(T)) +{ + freeSlots.push_back({.position = 0, .size = size}); +} + +template GPU_BufferSlot* GPU_Buffer::FindFreeSlot(size_t size) +{ + for (auto i = freeSlots.rbegin(); i != freeSlots.rend(); i++) + { + if (i->size >= size) + return &(*i); + } + return nullptr; +} + +template size_t GPU_Buffer::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 void GPU_Buffer::Clear(GPU_BufferSlot range) +// { +// freeSlots.push_back(range); +// //TODO: insert sorted by pos and combine intersections +// } \ No newline at end of file diff --git a/frontend/include/GPU_Types/GPU_RenderUBO.hpp b/frontend/include/GPU_Types/GPU_RenderUBO.hpp new file mode 100644 index 0000000..97830d2 --- /dev/null +++ b/frontend/include/GPU_Types/GPU_RenderUBO.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "GPU_BaseTypes.hpp" +#include + +struct GPU_GlobalUBO +{ + glm::mat4 view; + glm::mat4 proj; + float time; +}; + +struct GPU_TranformUBO +{ + glm::mat4 model; + + void Update(const GPU_Transform &tranform); +}; \ No newline at end of file diff --git a/frontend/include/PipelineFactory.hpp b/frontend/include/PipelineFactory.hpp index 16db0db..cf3aa24 100644 --- a/frontend/include/PipelineFactory.hpp +++ b/frontend/include/PipelineFactory.hpp @@ -38,6 +38,10 @@ struct PipelineConfig VkViewport defaultViewport; VkRect2D defaultScissors; std::vector dynamicStates; + + std::vector uniforms; + int vertexBindingsCount, fragmentBindingsCount; + VkDescriptorSetLayoutCreateInfo uniformsConfig; VkGraphicsPipelineCreateInfo pipelineConfig; @@ -48,6 +52,7 @@ struct Pipeline { VkPipeline instance; VkPipelineLayout layout; + VkDescriptorSetLayout uniformsLayout; VkViewport viewport; VkRect2D scissors; }; diff --git a/frontend/include/Renderer.hpp b/frontend/include/Renderer.hpp index 69cd2a8..90bd683 100644 --- a/frontend/include/Renderer.hpp +++ b/frontend/include/Renderer.hpp @@ -2,14 +2,14 @@ #include #include #include -#include #include #include #include #define GLFW_INCLUDE_VULKAN #include -#include + +#include "GPU_Types/GPU_BaseTypes.hpp" #include "PipelineFactory.hpp" @@ -19,10 +19,6 @@ #define VALIDATION_LAYER #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 #define GPU_DISCRETE_PRIORITY 1000 #define GPU_GRAPHICS_WITH_PRESENT_PRIORITY 500 @@ -36,84 +32,6 @@ #define INDICES_SIZE uint16_t #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 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 struct GPU_Buffer -{ - T *data; - size_t size; - const size_t ELEMENT_SIZE; - std::vector 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 { size_t verticesBufferPosition = 0; @@ -122,19 +40,27 @@ struct Mesh std::vector 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 transforms; + std::vector transforms; uint8_t depth = 0; Mesh mesh; bool isUI = false; //TODO: texture AssetMaterial &material; - //TODO: materialParams (uniforms) + MaterialParams materialParams; }; bool operator < (const RenderObject& lhs, const RenderObject& rhs); @@ -268,6 +194,10 @@ private: VkBuffer stagingWorldIndices; VkBuffer uiVertices; VkBuffer uiIndices; + std::vector worldUniformsMemory; + std::vector worldUniforms; + std::vector uiUniformsMemory; + std::vector uiUniforms; std::vector graphicsCommandBuffers; std::vector transferCommandBuffers; std::vector frames; diff --git a/frontend/src/GPU_Types.cpp b/frontend/src/GPU_Types.cpp new file mode 100644 index 0000000..f815be6 --- /dev/null +++ b/frontend/src/GPU_Types.cpp @@ -0,0 +1,29 @@ +#include "GPU_Types/GPU_BaseTypes.hpp" +#include "GPU_Types/GPU_RenderUBO.hpp" + +#include + +std::array 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); +} \ No newline at end of file diff --git a/frontend/src/PipelineFactory.cpp b/frontend/src/PipelineFactory.cpp index 83e729b..daf7871 100644 --- a/frontend/src/PipelineFactory.cpp +++ b/frontend/src/PipelineFactory.cpp @@ -10,6 +10,7 @@ PipelineConfig PipelineConfig::Copy() const 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; @@ -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 }); + 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, @@ -89,11 +104,16 @@ PipelineFactory::PipelineFactory(const PipelineBinding &binding) : .pDynamicStates = basePipelineConfig.dynamicStates.data() }; + basePipelineConfig.uniformsConfig = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .bindingCount = static_cast(basePipelineConfig.uniforms.size()), + .pBindings = basePipelineConfig.uniforms.data() + }; + basePipelineConfig.pipelineLayoutConfig = { .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .pNext = nullptr, - .setLayoutCount = 0, //TODO: vector - .pSetLayouts = nullptr, + .setLayoutCount = 1, .pushConstantRangeCount = 0, .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) { + VkResult vkResult; + Pipeline newPipeline {}; Pipeline *result = &basePipeline; @@ -172,16 +194,6 @@ void PipelineFactory::Create(const AssetMaterial &material, const VkRenderPass & result = &newPipeline; 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 AssetHandle shaderHandle; @@ -213,6 +225,13 @@ void PipelineFactory::Create(const AssetMaterial &material, const VkRenderPass & .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); @@ -235,6 +254,26 @@ void PipelineFactory::Create(const AssetMaterial &material, const VkRenderPass & .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(stagesConfigs.size()); config->pipelineConfig.pStages = stagesConfigs.data(); config->pipelineConfig.renderPass = renderPass; @@ -265,9 +304,11 @@ 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); } } \ No newline at end of file diff --git a/frontend/src/main.cpp b/frontend/src/main.cpp index a22dc9b..446eea9 100644 --- a/frontend/src/main.cpp +++ b/frontend/src/main.cpp @@ -48,7 +48,7 @@ int main(int argc, char **argv) // Test render obj RenderObject triangle { - .transforms = {{.x = 0, .y = 0}}, + .transforms = {{.pos = {0.0f, 0.0f, 0.0f}}}, .mesh = { .vertices = { {.pos = {-0.5f, -0.5f}, .color = {0.0f, 0.0f, 0.0f}}, @@ -61,7 +61,7 @@ int main(int argc, char **argv) .material = baseMaterial, }; RenderObject rect { - .transforms = {{.x = 0, .y = 0}}, + .transforms = {{.pos = {0.0f, 0.0f, 0.0f}}}, .mesh = { .vertices = { {.pos = {-0.5f, -0.5f}, .color = {1.0f, 0.0f, 0.0f}}, diff --git a/sdk/shaders/helloworld/helloworld.vert b/sdk/shaders/helloworld/helloworld.vert index 92a086e..6ea328c 100644 --- a/sdk/shaders/helloworld/helloworld.vert +++ b/sdk/shaders/helloworld/helloworld.vert @@ -1,12 +1,21 @@ #version 450 #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 = 1) in vec3 inColor; layout(location = 0) out vec3 fragColor; 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; } \ No newline at end of file