From 945cf4b1ccc7e542d5d7ab4c25e9e179377b7436 Mon Sep 17 00:00:00 2001 From: legatt Date: Wed, 14 Jan 2026 15:26:09 +0300 Subject: [PATCH] UBO base --- assets/shaders/helloworld.vert.spv | Bin 1116 -> 1812 bytes frontend/CMakeLists.txt | 13 +-- frontend/include/AssetData.hpp | 6 ++ frontend/include/GPU_Types/GPU_BaseTypes.hpp | 84 +++++++++++++++ frontend/include/GPU_Types/GPU_RenderUBO.hpp | 18 ++++ frontend/include/PipelineFactory.hpp | 5 + frontend/include/Renderer.hpp | 102 +++---------------- frontend/src/GPU_Types.cpp | 29 ++++++ frontend/src/PipelineFactory.cpp | 65 +++++++++--- frontend/src/main.cpp | 4 +- sdk/shaders/helloworld/helloworld.vert | 11 +- 11 files changed, 230 insertions(+), 107 deletions(-) create mode 100644 frontend/include/GPU_Types/GPU_BaseTypes.hpp create mode 100644 frontend/include/GPU_Types/GPU_RenderUBO.hpp create mode 100644 frontend/src/GPU_Types.cpp diff --git a/assets/shaders/helloworld.vert.spv b/assets/shaders/helloworld.vert.spv index 7d2aebb5b5e7a24c76f23d476fd89154fba2ebb0..4062a52f5ade3614b80355199b9356cc9556f7b7 100644 GIT binary patch literal 1812 zcmZ9L+fLL_6oxA^0|){la!_%c0naFcr#Y;M=}d+eJCXF{?pc_3Mr)buwb{YwRP<+~kkJTP`;qQSHCJa%`G_=lTu7$R8?3dGer;F9-m zs{)&2wZ)hl3~e!Lz~IMX*kJ67-tbcNE;y2_TZ(*Q9DTUXc?mr%##=bsCAZvLt;7Gn z4vf0j61U{GEt_NgrNYf;gI7D7<=Ea~{puYSv$N5YJ#YtiTmRo3^?aVDVjSY^qw24h zKJ_!2hI!iJ4IZ)QWDQHVB=f3g9(?$n)$gcuOTt+xeg2c_wDG6smKKr9Db2atL9>Ea$Uy$ZK;Pl7m+Xu7#F3P4q z`Lkt=`lhCUd)sTVjDgV$pFPkEj@r_^8J}KD()0xNj + + // 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