diff --git a/openVulkanoCpp/Base/Utils.hpp b/openVulkanoCpp/Base/Utils.hpp index 191eff4..aacbe41 100644 --- a/openVulkanoCpp/Base/Utils.hpp +++ b/openVulkanoCpp/Base/Utils.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "Data/Containers/Array.hpp" namespace openVulkanoCpp diff --git a/openVulkanoCpp/ExampleApps/CubesExampleApp.cpp b/openVulkanoCpp/ExampleApps/CubesExampleApp.cpp index fcbbd13..b90309b 100644 --- a/openVulkanoCpp/ExampleApps/CubesExampleApp.cpp +++ b/openVulkanoCpp/ExampleApps/CubesExampleApp.cpp @@ -62,7 +62,7 @@ public: { Geometry* geo = new Geometry(); geo->InitCube(std::rand() % 1000 / 1000.0f + 0.01f, std::rand() % 1000 / 1000.0f + 0.01f, std::rand() % 1000 / 1000.0f + 0.01f, Vector4f((std::rand() % 255) / 255.0f, (std::rand() % 255) / 255.0f, (std::rand() % 255) / 255.0f, 1)); - drawablesPool[i].Init(geo, &mat); + drawablesPool[i].Init(&shader, geo, &mat); } nodesPool.resize(OBJECTS); for(int i = 0; i < OBJECTS; i++) @@ -74,8 +74,6 @@ public: nodesPool[i].SetMatrix(Utils::translate(glm::mat4x4(1), Vector3f((std::rand() % 10000) / 1000.0f - 5, (std::rand() % 10000) / 1000.0f - 5, (std::rand() % 10000) / 1000.0f - 5))); } - scene.shader = &shader; - GetGraphicsAppManager()->GetRenderer()->SetScene(&scene); camController.Init(&cam); diff --git a/openVulkanoCpp/Scene/Drawable.hpp b/openVulkanoCpp/Scene/Drawable.hpp index c7eacf9..d2cd767 100644 --- a/openVulkanoCpp/Scene/Drawable.hpp +++ b/openVulkanoCpp/Scene/Drawable.hpp @@ -8,25 +8,38 @@ #include "Base/ICloseable.hpp" #include "DrawEncoder.hpp" +#include #include namespace openVulkanoCpp::Scene { class Node; class Scene; + class Shader; - class Drawable + enum class DrawPhase + { + BACKGROUND = 0, MAIN, TRANSPARENT, POST + }; + + class Drawable : public ICloseable { std::vector m_nodes; Scene* m_scene = nullptr; + Shader* m_shader = nullptr; const DrawEncoder m_encoder; + const DrawPhase m_drawPhase; public: - explicit Drawable(const DrawEncoder& encoder) : m_encoder(encoder) {} + explicit Drawable(const DrawEncoder& encoder, + const DrawPhase phase = DrawPhase::MAIN) + : m_encoder(encoder), m_drawPhase(phase) {} - ~Drawable() { if (m_scene) Drawable::Close(); } + ~Drawable() override { if (m_scene) Drawable::Close(); } - void Close(); + void Close() override; + + void SetShader(Shader* shader) { m_shader = shader; } [[nodiscard]] virtual Drawable* Copy() = 0; @@ -36,6 +49,10 @@ namespace openVulkanoCpp::Scene [[nodiscard]] const DrawEncoder& GetEncoder() const { return m_encoder; } + [[nodiscard]] DrawPhase GetDrawPhase() const { return m_drawPhase; } + + [[nodiscard]] Shader* GetShader() const { return m_shader; } + private: friend class Node; friend class Scene; diff --git a/openVulkanoCpp/Scene/Scene.hpp b/openVulkanoCpp/Scene/Scene.hpp index 7372c38..2ab6a02 100644 --- a/openVulkanoCpp/Scene/Scene.hpp +++ b/openVulkanoCpp/Scene/Scene.hpp @@ -22,7 +22,6 @@ namespace openVulkanoCpp public: Node* root; std::vector shapeList; - Shader* shader; Camera* camera; public: diff --git a/openVulkanoCpp/Scene/Shader.hpp b/openVulkanoCpp/Scene/Shader.hpp index 66cdd1d..10d4d9e 100644 --- a/openVulkanoCpp/Scene/Shader.hpp +++ b/openVulkanoCpp/Scene/Shader.hpp @@ -125,8 +125,9 @@ namespace openVulkanoCpp::Scene } }; - struct Shader final : public virtual ICloseable + class Shader final : public ICloseable { + public: std::vector shaderPrograms{}; std::vector vertexInputDescriptions{}; Topology topology = Topology::TRIANGLE_LIST; @@ -162,7 +163,7 @@ namespace openVulkanoCpp::Scene 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 < 0) bindingId = static_cast(vertexInputDescriptions.size()); if (bindingId > vertexInputDescriptions.size()) { vertexInputDescriptions.emplace_back(0, 0); diff --git a/openVulkanoCpp/Scene/SimpleDrawable.cpp b/openVulkanoCpp/Scene/SimpleDrawable.cpp index 611e827..a61338a 100644 --- a/openVulkanoCpp/Scene/SimpleDrawable.cpp +++ b/openVulkanoCpp/Scene/SimpleDrawable.cpp @@ -9,11 +9,12 @@ namespace openVulkanoCpp::Scene { - void SimpleDrawable::Init(Geometry* mesh, Material* material) + void SimpleDrawable::Init(Shader* shader, Geometry* mesh, Material* material) { if (m_mesh || m_material) throw std::runtime_error("Drawable is already initialized."); m_mesh = mesh; m_material = material; + SetShader(shader); } void SimpleDrawable::Init(SimpleDrawable* drawable) @@ -21,5 +22,6 @@ namespace openVulkanoCpp::Scene if (m_mesh || m_material) throw std::runtime_error("Drawable is already initialized."); m_mesh = drawable->m_mesh; m_material = drawable->m_material; + SetShader(drawable->GetShader()); } } \ No newline at end of file diff --git a/openVulkanoCpp/Scene/SimpleDrawable.hpp b/openVulkanoCpp/Scene/SimpleDrawable.hpp index 041c65c..273e14b 100644 --- a/openVulkanoCpp/Scene/SimpleDrawable.hpp +++ b/openVulkanoCpp/Scene/SimpleDrawable.hpp @@ -19,20 +19,23 @@ namespace openVulkanoCpp::Scene Material* m_material = nullptr; public: - SimpleDrawable() : Drawable(DrawEncoder::GetDrawEncoder()) {} + SimpleDrawable() : Drawable(DrawEncoder::GetDrawEncoder()) + {} explicit SimpleDrawable(const SimpleDrawable* toCopy) : Drawable(DrawEncoder::GetDrawEncoder()) , m_mesh(toCopy->m_mesh) , m_material(toCopy->m_material) - {} + { + SetShader(toCopy->GetShader()); + } ~SimpleDrawable() { if (m_mesh) SimpleDrawable::Close(); } - void Init(Geometry* mesh, Material* material); + void Init(Shader* shader, Geometry* mesh, Material* material); void Init(SimpleDrawable* drawable); diff --git a/openVulkanoCpp/Vulkan/Renderer.cpp b/openVulkanoCpp/Vulkan/Renderer.cpp index 307b723..a2595b8 100644 --- a/openVulkanoCpp/Vulkan/Renderer.cpp +++ b/openVulkanoCpp/Vulkan/Renderer.cpp @@ -59,8 +59,6 @@ namespace openVulkanoCpp::Vulkan } } - shader = resourceManager.CreateShader(scene->shader); - logger->info("Vulkan renderer initialized"); } @@ -145,15 +143,12 @@ namespace openVulkanoCpp::Vulkan void Renderer::RecordSecondaryBuffer(Data::ReadOnlyAtomicArrayQueue* jobQueue, uint32_t poolId) { - Scene::Geometry* lastGeo = nullptr; - Scene::Node* lastNode = nullptr; CommandHelper* cmdHelper = GetCommandData(poolId); cmdHelper->Reset(); vk::CommandBufferInheritanceInfo inheritance = { context.swapChainRenderPass.renderPass, 0, context.swapChainRenderPass.GetFrameBuffer()->GetCurrentFrameBuffer() }; cmdHelper->cmdBuffer.begin(vk::CommandBufferBeginInfo{ vk::CommandBufferUsageFlagBits::eOneTimeSubmit | vk::CommandBufferUsageFlagBits::eRenderPassContinue, &inheritance }); cmdHelper->cmdBuffer.pushConstants(context.pipeline.pipelineLayout, vk::ShaderStageFlagBits::eVertex, 0, 3 * sizeof(Math::Matrix4f) + sizeof(Math::Vector4f) + 4 * sizeof(float), &scene->GetCamera()->GetViewProjectionMatrix()); - shader->Record(cmdHelper->cmdBuffer, currentImageId); Scene::Drawable** drawablePointer; VulkanDrawContext drawContext { poolId, currentImageId, cmdHelper->cmdBuffer, this }; while((drawablePointer = jobQueue->Pop()) != nullptr) diff --git a/openVulkanoCpp/Vulkan/Renderer.hpp b/openVulkanoCpp/Vulkan/Renderer.hpp index 285fc71..c9891e0 100644 --- a/openVulkanoCpp/Vulkan/Renderer.hpp +++ b/openVulkanoCpp/Vulkan/Renderer.hpp @@ -37,7 +37,6 @@ namespace openVulkanoCpp::Vulkan std::vector> commands; std::vector> submitBuffers; UiRenderer uiRenderer; - VulkanShader* shader; public: Renderer() = default; diff --git a/openVulkanoCpp/Vulkan/Scene/SimpleDrawableVulkanEncoder.cpp b/openVulkanoCpp/Vulkan/Scene/SimpleDrawableVulkanEncoder.cpp index 0158e20..8a4f70b 100644 --- a/openVulkanoCpp/Vulkan/Scene/SimpleDrawableVulkanEncoder.cpp +++ b/openVulkanoCpp/Vulkan/Scene/SimpleDrawableVulkanEncoder.cpp @@ -15,6 +15,7 @@ namespace openVulkanoCpp::Vulkan { void EncodeSimpleDrawable(Drawable* instance, Vulkan::VulkanDrawContext* drawContext) { + drawContext->EncodeShader(instance->GetShader()); Geometry* mesh = dynamic_cast(instance)->GetMesh(); VulkanGeometry* renderGeo = dynamic_cast(mesh->renderGeo); if (!mesh->renderGeo) renderGeo = drawContext->renderer->GetResourceManager().PrepareGeometry(mesh); diff --git a/openVulkanoCpp/Vulkan/Scene/VulkanShader.hpp b/openVulkanoCpp/Vulkan/Scene/VulkanShader.hpp index 715ab4b..961d98e 100644 --- a/openVulkanoCpp/Vulkan/Scene/VulkanShader.hpp +++ b/openVulkanoCpp/Vulkan/Scene/VulkanShader.hpp @@ -23,15 +23,15 @@ namespace openVulkanoCpp class Context; class IShaderOwner; - struct VulkanShader final : virtual public ICloseable, virtual public IRecordable + struct VulkanShader final : public ICloseable, public IRecordable { Scene::Shader* shader = nullptr; vk::Device device; std::vector shaderModules; // TODO manage live time somewhere else to allow sharing of shader programs std::vector shaderStageCreateInfo; vk::Pipeline pipeline; // TODO pipeline and shader config should be split - IShaderOwner* owner; - Context* context; + IShaderOwner* owner = nullptr; + Context* context = nullptr; VulkanShader() = default; diff --git a/openVulkanoCpp/Vulkan/VulkanDrawContext.cpp b/openVulkanoCpp/Vulkan/VulkanDrawContext.cpp new file mode 100644 index 0000000..a1e5fd4 --- /dev/null +++ b/openVulkanoCpp/Vulkan/VulkanDrawContext.cpp @@ -0,0 +1,24 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include "VulkanDrawContext.hpp" +#include "Scene/Shader.hpp" +#include "Scene/VulkanShader.hpp" + +namespace openVulkanoCpp::Vulkan +{ + void VulkanDrawContext::EncodeShader(Scene::Shader* shader) + { + VulkanShader* vkShader = static_cast(shader->renderShader); + if (!vkShader) + { + vkShader = renderer->GetResourceManager().CreateShader(shader); + } + else if (m_lastShader == vkShader) return; // Skip it if shader is already bound + vkShader->Record(commandBuffer, currentImageId); + m_lastShader = vkShader; + } +} \ No newline at end of file diff --git a/openVulkanoCpp/Vulkan/VulkanDrawContext.hpp b/openVulkanoCpp/Vulkan/VulkanDrawContext.hpp index 069c1fd..e776193 100644 --- a/openVulkanoCpp/Vulkan/VulkanDrawContext.hpp +++ b/openVulkanoCpp/Vulkan/VulkanDrawContext.hpp @@ -10,10 +10,18 @@ namespace openVulkanoCpp::Vulkan { class VulkanDrawContext { + VulkanShader* m_lastShader = nullptr; + public: size_t encoderThreadId; size_t currentImageId; vk::CommandBuffer& commandBuffer; Renderer* renderer; + + VulkanDrawContext(size_t encThreadId, size_t currentImgId, vk::CommandBuffer& buffer, Renderer* render) + : encoderThreadId(encThreadId), currentImageId(currentImgId), commandBuffer(buffer), renderer(render) + {} + + void EncodeShader(Scene::Shader* shader); }; }