Move Drawable draw call recording logic out of renderer
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
#include "Scene/Geometry.hpp"
|
||||
#include "Scene/Material.hpp"
|
||||
#include "Scene/Vertex.hpp"
|
||||
#include "Scene/SimpleDrawable.hpp"
|
||||
#include "Input/InputManager.hpp"
|
||||
#include "Host/GraphicsAppManager.hpp"
|
||||
#include "Math/Math.hpp"
|
||||
@@ -33,7 +34,7 @@ class CubesExampleAppImpl final : public CubesExampleApp
|
||||
openVulkanoCpp::FreeCamCameraController camController;
|
||||
Material mat;
|
||||
Shader shader;
|
||||
std::vector<Drawable> drawablesPool;
|
||||
std::vector<SimpleDrawable> drawablesPool;
|
||||
std::vector<Node> nodesPool;
|
||||
|
||||
InputAction* actionForward;
|
||||
|
||||
42
openVulkanoCpp/Scene/DrawEncoder.cpp
Normal file
42
openVulkanoCpp/Scene/DrawEncoder.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 "DrawEncoder.hpp"
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace openVulkanoCpp::Scene
|
||||
{
|
||||
namespace
|
||||
{
|
||||
auto& GetDrawEncoderRegistry()
|
||||
{
|
||||
static std::map<const std::type_info*, DrawEncoder> drawEncoderRegistry;
|
||||
return drawEncoderRegistry;
|
||||
}
|
||||
|
||||
template<class... args>
|
||||
void EncoderNotImplementedFunction(args... ignored)
|
||||
{
|
||||
throw std::runtime_error("No implementation for encoder!");
|
||||
}
|
||||
}
|
||||
|
||||
void* DrawEncoder::RegisterVulkanEncodeFunction(const std::type_info* type, DrawEncoder::VkEncodeFunc func)
|
||||
{
|
||||
GetDrawEncoderRegistry()[type].vulkan = func;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DrawEncoder& DrawEncoder::GetDrawEncoder(const std::type_info* type)
|
||||
{
|
||||
return GetDrawEncoderRegistry()[type];
|
||||
}
|
||||
|
||||
DrawEncoder::DrawEncoder()
|
||||
: vulkan(&EncoderNotImplementedFunction)
|
||||
{}
|
||||
}
|
||||
59
openVulkanoCpp/Scene/DrawEncoder.hpp
Normal file
59
openVulkanoCpp/Scene/DrawEncoder.hpp
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
namespace openVulkanoCpp
|
||||
{
|
||||
namespace Vulkan
|
||||
{
|
||||
class VulkanDrawContext;
|
||||
}
|
||||
|
||||
namespace Scene
|
||||
{
|
||||
class Drawable;
|
||||
|
||||
struct DrawEncoder
|
||||
{
|
||||
//region function type definitions
|
||||
typedef void(* VkEncodeFunc)(Drawable*, Vulkan::VulkanDrawContext*);
|
||||
//endregion
|
||||
|
||||
//region DrawEncoder storage
|
||||
VkEncodeFunc vulkan;
|
||||
//endregion
|
||||
|
||||
//region DrawEncoder constructors
|
||||
DrawEncoder();
|
||||
|
||||
DrawEncoder(const DrawEncoder& other) = default;
|
||||
//endregion
|
||||
|
||||
//region static functions
|
||||
static void* RegisterVulkanEncodeFunction(const std::type_info* type, VkEncodeFunc func);
|
||||
|
||||
static DrawEncoder& GetDrawEncoder(const std::type_info* type);
|
||||
//endregion
|
||||
|
||||
//region Template helper functions
|
||||
template<class T>
|
||||
static DrawEncoder& GetDrawEncoder()
|
||||
{
|
||||
return { GetDrawEncoder(&typeid(T)) };
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static void* RegisterVulkanEncodeFunction(VkEncodeFunc func)
|
||||
{
|
||||
return RegisterVulkanEncodeFunction(&typeid(T), func);
|
||||
}
|
||||
//endregion
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -10,19 +10,24 @@
|
||||
|
||||
namespace openVulkanoCpp::Scene
|
||||
{
|
||||
void Drawable::Close()
|
||||
{
|
||||
if (!m_nodes.empty()) throw std::runtime_error("Drawable is still being used!!!");
|
||||
m_scene = nullptr;
|
||||
}
|
||||
|
||||
void Drawable::SetScene(Scene* scene)
|
||||
{
|
||||
if (m_scene == scene) return;
|
||||
if (scene && m_scene) throw std::runtime_error("Drawable has been associated with a scene already!");
|
||||
const auto oldScene = m_scene;
|
||||
m_scene = scene;
|
||||
if(scene) scene->RegisterDrawable(this);
|
||||
if (scene) scene->RegisterDrawable(this);
|
||||
else if (oldScene) oldScene->RemoveDrawable(this);
|
||||
}
|
||||
|
||||
void Drawable::AddNode(Node* node)
|
||||
{
|
||||
if (!m_mesh) throw std::runtime_error("Drawable is not initialized.");
|
||||
if (Utils::Contains(m_nodes, node)) throw std::runtime_error("A drawable must not use the same node more than once.");
|
||||
m_nodes.push_back(node);
|
||||
}
|
||||
@@ -36,25 +41,4 @@ namespace openVulkanoCpp::Scene
|
||||
m_scene = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Drawable::Init(Geometry* mesh, Material* material)
|
||||
{
|
||||
if (m_mesh || m_material) throw std::runtime_error("Drawable is already initialized.");
|
||||
m_mesh = mesh;
|
||||
m_material = material;
|
||||
}
|
||||
|
||||
void Drawable::Init(Drawable* drawable)
|
||||
{
|
||||
if (m_mesh || m_material) throw std::runtime_error("Drawable is already initialized.");
|
||||
m_mesh = drawable->m_mesh;
|
||||
m_material = drawable->m_material;
|
||||
}
|
||||
|
||||
void Drawable::Close()
|
||||
{
|
||||
if (!m_nodes.empty()) throw std::runtime_error("Drawable is still being used!!!");
|
||||
m_mesh = nullptr;
|
||||
m_material = nullptr;
|
||||
}
|
||||
}
|
||||
@@ -7,53 +7,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "Base/ICloseable.hpp"
|
||||
#include "DrawEncoder.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace openVulkanoCpp::Scene
|
||||
{
|
||||
class Node;
|
||||
class Scene;
|
||||
class Geometry;
|
||||
class Material;
|
||||
|
||||
class Drawable : virtual public ICloseable
|
||||
class Drawable
|
||||
{
|
||||
std::vector<Node*> m_nodes;
|
||||
Scene* m_scene = nullptr;
|
||||
Geometry* m_mesh = nullptr;
|
||||
Material* m_material = nullptr;
|
||||
const DrawEncoder m_encoder;
|
||||
|
||||
public:
|
||||
Drawable() = default;
|
||||
explicit Drawable(const DrawEncoder& encoder) : m_encoder(encoder) {}
|
||||
|
||||
explicit Drawable(const Drawable* toCopy)
|
||||
{
|
||||
m_mesh = toCopy->m_mesh;
|
||||
m_material = toCopy->m_material;
|
||||
}
|
||||
~Drawable() { if (m_scene) Drawable::Close(); }
|
||||
|
||||
~Drawable() override
|
||||
{
|
||||
if (m_mesh) Drawable::Close();
|
||||
}
|
||||
void Close();
|
||||
|
||||
[[nodiscard]] Drawable* Copy() const
|
||||
{
|
||||
return new Drawable(this);
|
||||
}
|
||||
|
||||
void Init(Geometry* mesh, Material* material);
|
||||
|
||||
void Init(Drawable* drawable);
|
||||
|
||||
void Close() override;
|
||||
[[nodiscard]] virtual Drawable* Copy() = 0;
|
||||
|
||||
[[nodiscard]] Scene* GetScene() const { return m_scene; }
|
||||
|
||||
[[nodiscard]] Geometry* GetMesh() const { return m_mesh; }
|
||||
|
||||
[[nodiscard]] const auto& GetNodes() const { return m_nodes; }
|
||||
|
||||
[[nodiscard]] const DrawEncoder& GetEncoder() const { return m_encoder; }
|
||||
|
||||
private:
|
||||
friend class Node;
|
||||
friend class Scene;
|
||||
|
||||
@@ -23,8 +23,9 @@ namespace openVulkanoCpp
|
||||
UINT16 = sizeof(uint16_t), UINT32 = sizeof(uint32_t)
|
||||
};
|
||||
|
||||
struct Geometry : public virtual ICloseable
|
||||
class Geometry : public virtual ICloseable
|
||||
{
|
||||
public:
|
||||
uint32_t vertexCount = 0, indexCount = 0;
|
||||
Vertex* vertices;
|
||||
void* indices;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "Drawable.hpp"
|
||||
#include "UpdateFrequency.hpp"
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
namespace openVulkanoCpp::Scene
|
||||
{
|
||||
|
||||
25
openVulkanoCpp/Scene/SimpleDrawable.cpp
Normal file
25
openVulkanoCpp/Scene/SimpleDrawable.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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 "SimpleDrawable.hpp"
|
||||
#include <stdexcept>
|
||||
|
||||
namespace openVulkanoCpp::Scene
|
||||
{
|
||||
void SimpleDrawable::Init(Geometry* mesh, Material* material)
|
||||
{
|
||||
if (m_mesh || m_material) throw std::runtime_error("Drawable is already initialized.");
|
||||
m_mesh = mesh;
|
||||
m_material = material;
|
||||
}
|
||||
|
||||
void SimpleDrawable::Init(SimpleDrawable* drawable)
|
||||
{
|
||||
if (m_mesh || m_material) throw std::runtime_error("Drawable is already initialized.");
|
||||
m_mesh = drawable->m_mesh;
|
||||
m_material = drawable->m_material;
|
||||
}
|
||||
}
|
||||
45
openVulkanoCpp/Scene/SimpleDrawable.hpp
Normal file
45
openVulkanoCpp/Scene/SimpleDrawable.hpp
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Drawable.hpp"
|
||||
|
||||
namespace openVulkanoCpp::Scene
|
||||
{
|
||||
class Geometry;
|
||||
class Material;
|
||||
|
||||
class SimpleDrawable final : public Drawable
|
||||
{
|
||||
Geometry* m_mesh = nullptr;
|
||||
Material* m_material = nullptr;
|
||||
|
||||
public:
|
||||
SimpleDrawable() : Drawable(DrawEncoder::GetDrawEncoder<SimpleDrawable>()) {}
|
||||
|
||||
explicit SimpleDrawable(const SimpleDrawable* toCopy)
|
||||
: Drawable(DrawEncoder::GetDrawEncoder<SimpleDrawable>())
|
||||
, m_mesh(toCopy->m_mesh)
|
||||
, m_material(toCopy->m_material)
|
||||
{}
|
||||
|
||||
~SimpleDrawable()
|
||||
{
|
||||
if (m_mesh) SimpleDrawable::Close();
|
||||
}
|
||||
|
||||
void Init(Geometry* mesh, Material* material);
|
||||
|
||||
void Init(SimpleDrawable* drawable);
|
||||
|
||||
[[nodiscard]] Drawable* Copy() override { return new SimpleDrawable(this); }
|
||||
|
||||
[[nodiscard]] Geometry* GetMesh() const { return m_mesh; }
|
||||
|
||||
[[nodiscard]] Material* GetMaterial() const { return m_material; }
|
||||
};
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include "Renderer.hpp"
|
||||
#include "VulkanDrawContext.hpp"
|
||||
#include "Scene/Shader.hpp"
|
||||
#include "Scene/Geometry.hpp"
|
||||
#include "Scene/VulkanGeometry.hpp"
|
||||
@@ -154,27 +155,11 @@ namespace openVulkanoCpp::Vulkan
|
||||
|
||||
shader->Record(cmdHelper->cmdBuffer, currentImageId);
|
||||
Scene::Drawable** drawablePointer;
|
||||
VulkanDrawContext drawContext { poolId, currentImageId, cmdHelper->cmdBuffer, this };
|
||||
while((drawablePointer = jobQueue->Pop()) != nullptr)
|
||||
{
|
||||
Scene::Drawable* drawable = *drawablePointer;
|
||||
Scene::Geometry* mesh = drawable->mesh;
|
||||
VulkanGeometry* renderGeo = dynamic_cast<VulkanGeometry*>(mesh->renderGeo);
|
||||
if (mesh != lastGeo)
|
||||
{
|
||||
if (!mesh->renderGeo) renderGeo = resourceManager.PrepareGeometry(mesh);
|
||||
renderGeo->RecordBind(cmdHelper->cmdBuffer);
|
||||
lastGeo = mesh;
|
||||
}
|
||||
for(Scene::Node* node : drawable->nodes)
|
||||
{
|
||||
if (node != lastNode)
|
||||
{
|
||||
if (!node->renderNode) resourceManager.PrepareNode(node);
|
||||
dynamic_cast<VulkanNode*>(node->renderNode)->Record(cmdHelper->cmdBuffer, currentImageId);
|
||||
lastNode = node;
|
||||
}
|
||||
renderGeo->RecordDraw(cmdHelper->cmdBuffer);
|
||||
}
|
||||
drawable->GetEncoder().vulkan(drawable, &drawContext);
|
||||
}
|
||||
cmdHelper->cmdBuffer.end();
|
||||
}
|
||||
|
||||
@@ -74,5 +74,7 @@ namespace openVulkanoCpp::Vulkan
|
||||
void Render();
|
||||
|
||||
void RecordSecondaryBuffer(Data::ReadOnlyAtomicArrayQueue<Scene::Drawable*>* jobQueue, uint32_t poolId);
|
||||
|
||||
ResourceManager& GetResourceManager() { return resourceManager; }
|
||||
};
|
||||
}
|
||||
|
||||
34
openVulkanoCpp/Vulkan/Scene/SimpleDrawableVulkanEncoder.cpp
Normal file
34
openVulkanoCpp/Vulkan/Scene/SimpleDrawableVulkanEncoder.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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 "Scene/SimpleDrawable.hpp"
|
||||
#include "VulkanGeometry.hpp"
|
||||
#include "VulkanNode.hpp"
|
||||
#include "Vulkan/VulkanDrawContext.hpp"
|
||||
|
||||
using namespace openVulkanoCpp::Scene;
|
||||
|
||||
namespace openVulkanoCpp::Vulkan
|
||||
{
|
||||
void EncodeSimpleDrawable(Drawable* instance, Vulkan::VulkanDrawContext* drawContext)
|
||||
{
|
||||
Geometry* mesh = dynamic_cast<SimpleDrawable*>(instance)->GetMesh();
|
||||
VulkanGeometry* renderGeo = dynamic_cast<VulkanGeometry*>(mesh->renderGeo);
|
||||
if (!mesh->renderGeo) renderGeo = drawContext->renderer->GetResourceManager().PrepareGeometry(mesh);
|
||||
renderGeo->RecordBind(drawContext->commandBuffer);
|
||||
for(Node* node : instance->GetNodes())
|
||||
{
|
||||
if (!node->renderNode) drawContext->renderer->GetResourceManager().PrepareNode(node);
|
||||
dynamic_cast<VulkanNode*>(node->renderNode)->Record(drawContext->commandBuffer, drawContext->currentImageId);
|
||||
renderGeo->RecordDraw(drawContext->commandBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
void* simpleDrawableVulkanEncoderReg = DrawEncoder::RegisterVulkanEncodeFunction<SimpleDrawable>(&openVulkanoCpp::Vulkan::EncodeSimpleDrawable);
|
||||
}
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "IRecordable.hpp"
|
||||
#include "Scene/Scene.hpp"
|
||||
#include "Scene/Geometry.hpp"
|
||||
#include "Vulkan/Resources/ManagedResource.hpp"
|
||||
|
||||
namespace openVulkanoCpp::Vulkan
|
||||
{
|
||||
|
||||
19
openVulkanoCpp/Vulkan/VulkanDrawContext.hpp
Normal file
19
openVulkanoCpp/Vulkan/VulkanDrawContext.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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 "Renderer.hpp"
|
||||
|
||||
namespace openVulkanoCpp::Vulkan
|
||||
{
|
||||
class VulkanDrawContext
|
||||
{
|
||||
public:
|
||||
size_t encoderThreadId;
|
||||
size_t currentImageId;
|
||||
vk::CommandBuffer& commandBuffer;
|
||||
Renderer* renderer;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user