diff --git a/openVulkanoCpp/ExampleApps/CubesExampleApp.cpp b/openVulkanoCpp/ExampleApps/CubesExampleApp.cpp index 54e77ac..c3f169a 100644 --- a/openVulkanoCpp/ExampleApps/CubesExampleApp.cpp +++ b/openVulkanoCpp/ExampleApps/CubesExampleApp.cpp @@ -52,6 +52,7 @@ public: cam.SetMatrix(Utils::translate(Matrix4f(1), Vector3f_SIMD(0,0,-10))); shader.AddShaderProgram(ShaderProgramType::VERTEX, "Shader/basic"); shader.AddShaderProgram(ShaderProgramType::FRAGMENT, "Shader/basic"); + shader.AddVertexInputDescription(openVulkanoCpp::Vertex::GetVertexInputDescription()); drawablesPool.resize(GEOS); for(int i = 0; i < GEOS; i++) { diff --git a/openVulkanoCpp/Scene/Shader.hpp b/openVulkanoCpp/Scene/Shader.hpp index d28c9f8..3e272a7 100644 --- a/openVulkanoCpp/Scene/Shader.hpp +++ b/openVulkanoCpp/Scene/Shader.hpp @@ -8,6 +8,7 @@ #include "Base/ICloseable.hpp" #include "Base/Utils.hpp" +#include "VertexInputDescription.hpp" #include #include @@ -119,6 +120,7 @@ namespace openVulkanoCpp::Scene struct Shader final : public virtual ICloseable { std::vector shaderPrograms{}; + std::vector vertexInputDescriptions{}; Topology topology = Topology::TRIANGLE_LIST; ICloseable* renderShader = nullptr; @@ -147,6 +149,25 @@ namespace openVulkanoCpp::Scene return *this; } + Shader& AddVertexInputDescription(const VertexInputDescription& inputDescription, int bindingId = -1) + { + if (renderShader) throw std::runtime_error("Shader already initialized!"); + if (bindingId < 0) bindingId = vertexInputDescriptions.size(); + if (bindingId > vertexInputDescriptions.size()) + { + vertexInputDescriptions.emplace_back(0, 0); + } + if (bindingId == vertexInputDescriptions.size()) + { + vertexInputDescriptions.emplace_back(bindingId, inputDescription); + } + else + { + vertexInputDescriptions[bindingId] = inputDescription; + } + return *this; + } + void Close() override { renderShader->Close(); diff --git a/openVulkanoCpp/Scene/Vertex.hpp b/openVulkanoCpp/Scene/Vertex.hpp index ed3e3c9..0ade909 100644 --- a/openVulkanoCpp/Scene/Vertex.hpp +++ b/openVulkanoCpp/Scene/Vertex.hpp @@ -7,6 +7,7 @@ #pragma once #include "Math/Math.hpp" +#include "VertexInputDescription.hpp" #include #include #include @@ -182,5 +183,17 @@ namespace openVulkanoCpp { this->color = { color.r, color.g, color.b, color.a }; } + + static VertexInputDescription GetVertexInputDescription() + { + VertexInputDescription description(0, sizeof(Vertex)); + description.AddInputParameter(DataFormat::R32G32B32_SFLOAT, offsetof(Vertex, position)); + description.AddInputParameter(DataFormat::R32G32B32_SFLOAT, offsetof(Vertex, normal)); + description.AddInputParameter(DataFormat::R32G32B32_SFLOAT, offsetof(Vertex, tangent)); + description.AddInputParameter(DataFormat::R32G32B32_SFLOAT, offsetof(Vertex, biTangent)); + description.AddInputParameter(DataFormat::R32G32B32_SFLOAT, offsetof(Vertex, textureCoordinates)); + description.AddInputParameter(DataFormat::R32G32B32A32_SFLOAT, offsetof(Vertex, color)); + return description; + } }; } diff --git a/openVulkanoCpp/Vulkan/Scene/VulkanShader.cpp b/openVulkanoCpp/Vulkan/Scene/VulkanShader.cpp index 7d76cfe..69b6890 100644 --- a/openVulkanoCpp/Vulkan/Scene/VulkanShader.cpp +++ b/openVulkanoCpp/Vulkan/Scene/VulkanShader.cpp @@ -6,7 +6,6 @@ #include "VulkanShader.hpp" #include "Vulkan/Context.hpp" -#include "Scene/Vertex.hpp" #include "Scene/Shader.hpp" #include "Vulkan/Resources/IShaderOwner.hpp" @@ -33,18 +32,39 @@ namespace openVulkanoCpp::Vulkan void VulkanShader::BuildPipeline() { - vk::VertexInputBindingDescription vertexBindDesc(0, sizeof(Vertex), vk::VertexInputRate::eVertex); + std::vector vertexBindDesc; std::vector attributeDescriptions; - attributeDescriptions.emplace_back(0, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, position)); - attributeDescriptions.emplace_back(1, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, normal)); - attributeDescriptions.emplace_back(2, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, tangent)); - attributeDescriptions.emplace_back(3, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, biTangent)); - attributeDescriptions.emplace_back(4, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, textureCoordinates)); - attributeDescriptions.emplace_back(5, 0, vk::Format::eR32G32B32A32Sfloat, offsetof(Vertex, color)); + vertexBindDesc.reserve(shader->vertexInputDescriptions.size()); + + for(const auto& description : shader->vertexInputDescriptions) + { + vertexBindDesc.emplace_back(description.bindingId, description.vertexSize, vk::VertexInputRate::eVertex); + if (shader->vertexInputDescriptions.size() > 1) + { + for(const auto& param : description.inputParameters) + { + attributeDescriptions.push_back(reinterpret_cast(param)); + } + } + } + uint32_t attributeDescriptionsSize; + vk::VertexInputAttributeDescription* attributeDescriptionsData; + if (shader->vertexInputDescriptions.size() == 1) + { // Reuse already existing vertex attribute description + static_assert(sizeof(VertexInputParameter) == sizeof(vk::VertexInputAttributeDescription)); + attributeDescriptionsSize = shader->vertexInputDescriptions[0].inputParameters.size(); + attributeDescriptionsData = reinterpret_cast(shader->vertexInputDescriptions[0].inputParameters.data()); + } + else + { + attributeDescriptionsSize = attributeDescriptions.size(); + attributeDescriptionsData = attributeDescriptions.data(); + } vk::PipelineViewportStateCreateInfo viewportStateCreateInfo = { {}, 1, &context->swapChain.GetFullscreenViewport(), 1, &context->swapChain.GetFullscreenScissor() }; - vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo = { {}, 1, &vertexBindDesc, - static_cast(attributeDescriptions.size()), attributeDescriptions.data() }; + vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo = { + {}, static_cast(vertexBindDesc.size()), vertexBindDesc.data(), + attributeDescriptionsSize, attributeDescriptionsData }; vk::PipelineInputAssemblyStateCreateInfo inputAssembly = { {}, static_cast(shader->topology), 0 }; vk::PipelineRasterizationStateCreateInfo rasterizer = {}; rasterizer.cullMode = vk::CullModeFlagBits::eBack;