asset_manager concept
This commit is contained in:
@@ -183,7 +183,16 @@ class Application::Impl {
|
||||
commandBuffer.setViewport(0, viewport);
|
||||
commandBuffer.setScissor(0, scissor);
|
||||
|
||||
modelRenderSystem.render(commandBuffer, this->meshes, frameInfo);
|
||||
std::vector<ModelRenderSystem::MeshInstance> instances;
|
||||
instances.reserve(this->meshes.size() + this->drawCalls.size());
|
||||
for (const std::unique_ptr<Mesh>& mesh : this->meshes) {
|
||||
instances.push_back({mesh.get(), glm::mat4{1.f}});
|
||||
}
|
||||
instances.insert(instances.end(), this->drawCalls.begin(),
|
||||
this->drawCalls.end());
|
||||
|
||||
modelRenderSystem.render(commandBuffer, instances, frameInfo);
|
||||
this->drawCalls.clear();
|
||||
|
||||
commandBuffer.endRendering();
|
||||
|
||||
@@ -224,6 +233,25 @@ class Application::Impl {
|
||||
this->meshes.clear();
|
||||
}
|
||||
|
||||
MeshHandle createMesh(std::vector<CanvasVertex> vertices,
|
||||
std::vector<u32> indices) {
|
||||
Mesh::Builder builder{};
|
||||
builder.vertices.reserve(vertices.size());
|
||||
for (const CanvasVertex& vertex : vertices) {
|
||||
builder.vertices.push_back({vertex.position, vertex.color});
|
||||
}
|
||||
builder.indices = std::move(indices);
|
||||
|
||||
this->persistentMeshes.push_back(
|
||||
std::make_unique<Mesh>(this->device, builder));
|
||||
return static_cast<MeshHandle>(this->persistentMeshes.size() - 1);
|
||||
}
|
||||
|
||||
void drawMesh(MeshHandle handle, const glm::mat4& transform) {
|
||||
this->drawCalls.push_back(
|
||||
{this->persistentMeshes[handle].get(), transform});
|
||||
}
|
||||
|
||||
private:
|
||||
Application& application;
|
||||
const Application::Config config;
|
||||
@@ -232,6 +260,8 @@ class Application::Impl {
|
||||
RenderContext renderContext;
|
||||
|
||||
std::vector<std::unique_ptr<Mesh>> meshes;
|
||||
std::vector<std::unique_ptr<Mesh>> persistentMeshes;
|
||||
std::vector<ModelRenderSystem::MeshInstance> drawCalls;
|
||||
};
|
||||
|
||||
void Application::setCommandLineArgs(int argc, const char* const* argv) {
|
||||
@@ -254,4 +284,13 @@ void Application::pushMesh(std::vector<CanvasVertex> vertices,
|
||||
|
||||
void Application::clearMeshes() { impl->clearMeshes(); }
|
||||
|
||||
MeshHandle Application::createMesh(std::vector<CanvasVertex> vertices,
|
||||
std::vector<u32> indices) {
|
||||
return impl->createMesh(std::move(vertices), std::move(indices));
|
||||
}
|
||||
|
||||
void Application::drawMesh(MeshHandle handle, const glm::mat4& transform) {
|
||||
impl->drawMesh(handle, transform);
|
||||
}
|
||||
|
||||
} // namespace sophia
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#include "assets/asset_manager.hpp"
|
||||
|
||||
#include "mesh.hpp"
|
||||
|
||||
namespace sophia {
|
||||
|
||||
AssetManager::AssetManager(Device& device) : device{device}, meshPool{device} {}
|
||||
|
||||
template <>
|
||||
MeshHandle AssetManager::create<Mesh>(const Mesh::Builder& builder) {
|
||||
return meshPool.create(builder);
|
||||
}
|
||||
|
||||
template <>
|
||||
const Mesh& AssetManager::get<Mesh>(MeshHandle handle) const {
|
||||
return meshPool.get(handle);
|
||||
}
|
||||
|
||||
template <>
|
||||
void AssetManager::release<Mesh>(MeshHandle handle) {
|
||||
meshPool.release(handle);
|
||||
}
|
||||
|
||||
} // namespace sophia
|
||||
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "device.hpp"
|
||||
#include "pools/mesh_pool.hpp"
|
||||
|
||||
namespace sophia {
|
||||
|
||||
class AssetManager {
|
||||
public:
|
||||
explicit AssetManager(Device& device);
|
||||
~AssetManager() = default;
|
||||
|
||||
AssetManager(const AssetManager&) = delete;
|
||||
AssetManager& operator=(const AssetManager&) = delete;
|
||||
|
||||
template <typename T>
|
||||
using HandleFor = typename T::HandleType;
|
||||
|
||||
template <typename T>
|
||||
HandleFor<T> load(const std::string& path);
|
||||
|
||||
template <typename T>
|
||||
HandleFor<T> create(const typename T::Builder& builder);
|
||||
|
||||
template <typename T>
|
||||
const T& get(HandleFor<T> handle) const;
|
||||
|
||||
template <typename T>
|
||||
void release(HandleFor<T> handle);
|
||||
|
||||
private:
|
||||
Device& device;
|
||||
|
||||
MeshPool meshPool;
|
||||
// TexturePool texturePool;
|
||||
// MaterialPool materialPool;
|
||||
};
|
||||
|
||||
} // namespace sophia
|
||||
@@ -0,0 +1,41 @@
|
||||
#include "assets/pools/mesh_pool.hpp"
|
||||
|
||||
#include <sophia/util/assert.hpp>
|
||||
|
||||
namespace sophia {
|
||||
|
||||
MeshPool::MeshPool(Device& device) : device{device} {}
|
||||
|
||||
MeshPool::~MeshPool() = default;
|
||||
|
||||
MeshHandle MeshPool::create(const Mesh::Builder& builder) {
|
||||
auto mesh = std::make_unique<Mesh>(device, builder);
|
||||
|
||||
if (!freeList.empty()) {
|
||||
MeshHandle handle = freeList.back();
|
||||
freeList.pop_back();
|
||||
meshes[handle] = std::move(mesh);
|
||||
return handle;
|
||||
}
|
||||
|
||||
meshes.push_back(std::move(mesh));
|
||||
return static_cast<MeshHandle>(meshes.size() - 1);
|
||||
}
|
||||
|
||||
const Mesh& MeshPool::get(MeshHandle handle) const {
|
||||
SOPHIA_ASSERT(handle < meshes.size(), "invalid MeshHandle:", handle);
|
||||
SOPHIA_ASSERT(meshes[handle] != nullptr,
|
||||
"MeshHandle refers to a released mesh:", handle);
|
||||
return *meshes[handle];
|
||||
}
|
||||
|
||||
void MeshPool::release(MeshHandle handle) {
|
||||
SOPHIA_ASSERT(handle < meshes.size(), "invalid MeshHandle:", handle);
|
||||
SOPHIA_ASSERT(meshes[handle] != nullptr,
|
||||
"MeshHandle already released:", handle);
|
||||
|
||||
meshes[handle].reset();
|
||||
freeList.push_back(handle);
|
||||
}
|
||||
|
||||
} // namespace sophia
|
||||
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "device.hpp"
|
||||
#include "mesh.hpp"
|
||||
|
||||
namespace sophia {
|
||||
|
||||
class MeshPool {
|
||||
public:
|
||||
explicit MeshPool(Device& device);
|
||||
~MeshPool();
|
||||
|
||||
MeshPool(const MeshPool&) = delete;
|
||||
MeshPool& operator=(const MeshPool&) = delete;
|
||||
|
||||
MeshHandle create(const Mesh::Builder& builder);
|
||||
const Mesh& get(MeshHandle handle) const;
|
||||
void release(MeshHandle handle);
|
||||
|
||||
private:
|
||||
Device& device;
|
||||
|
||||
std::vector<std::unique_ptr<Mesh>> meshes;
|
||||
std::vector<MeshHandle> freeList;
|
||||
};
|
||||
|
||||
} // namespace sophia
|
||||
@@ -0,0 +1,17 @@
|
||||
#include "scene.hpp"
|
||||
|
||||
#include <sophia/components.hpp>
|
||||
#include <sophia/util/logger.hpp>
|
||||
|
||||
namespace sophia {
|
||||
|
||||
Scene::Scene() {
|
||||
entt::entity entity = this->registry.create();
|
||||
|
||||
auto& a = this->registry.emplace<TransformComponent>(entity);
|
||||
auto& b = this->registry.get<TransformComponent>(entity);
|
||||
}
|
||||
|
||||
Scene::~Scene() { log::trace("destroying sophia::Scene"); }
|
||||
|
||||
} // namespace sophia
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <entt/entt.hpp>
|
||||
|
||||
namespace sophia {
|
||||
|
||||
class Scene {
|
||||
public:
|
||||
Scene();
|
||||
~Scene();
|
||||
|
||||
private:
|
||||
entt::registry registry;
|
||||
};
|
||||
|
||||
} // namespace sophia
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "model_render_system.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <sophia/util/assert.hpp>
|
||||
|
||||
#include "shaders/model_render_system.frag.spv.h"
|
||||
#include "shaders/model_render_system.vert.spv.h"
|
||||
@@ -12,8 +12,8 @@ ModelRenderSystem::ModelRenderSystem(Device& device,
|
||||
: device{device}, renderContext{renderContext} {
|
||||
createPipelineLayout();
|
||||
|
||||
assert(this->pipelineLayout.get() != nullptr &&
|
||||
"Cannot create pipeline before pipeline layout");
|
||||
SOPHIA_ASSERT(this->pipelineLayout.get() != nullptr,
|
||||
"Cannot create pipeline before pipeline layout");
|
||||
|
||||
auto vertexShader = Shader::Builder()
|
||||
.fromSPIRV(shaders::model_render_system_vert_spv)
|
||||
@@ -42,23 +42,23 @@ ModelRenderSystem::~ModelRenderSystem() {
|
||||
}
|
||||
|
||||
void ModelRenderSystem::render(vk::CommandBuffer commandBuffer,
|
||||
std::span<const std::unique_ptr<Mesh>> meshes,
|
||||
std::span<const MeshInstance> instances,
|
||||
const FrameInfo& frameInfo) {
|
||||
glm::mat4 viewProjection = frameInfo.camera.getViewProjection();
|
||||
|
||||
this->graphicsPipeline->bind(commandBuffer);
|
||||
|
||||
for (const std::unique_ptr<Mesh>& mesh : meshes) {
|
||||
for (const MeshInstance& instance : instances) {
|
||||
PushConstantData push{};
|
||||
push.modelMatrix = viewProjection;
|
||||
push.transform = viewProjection * instance.transform;
|
||||
|
||||
commandBuffer.pushConstants(
|
||||
this->pipelineLayout.get(),
|
||||
vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment,
|
||||
0, sizeof(PushConstantData), &push);
|
||||
|
||||
mesh->bind(commandBuffer);
|
||||
mesh->draw(commandBuffer);
|
||||
instance.mesh->bind(commandBuffer);
|
||||
instance.mesh->draw(commandBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,9 +13,15 @@ namespace sophia {
|
||||
|
||||
class ModelRenderSystem {
|
||||
public:
|
||||
// Layout must match the shader's `Push` block in model_render_system.vert.
|
||||
struct PushConstantData {
|
||||
glm::mat4 modelMatrix{1.f};
|
||||
glm::mat4 normalMatrix{1.f};
|
||||
glm::mat4 transform{1.f};
|
||||
glm::vec4 color{1.f};
|
||||
};
|
||||
|
||||
struct MeshInstance {
|
||||
const Mesh* mesh;
|
||||
glm::mat4 transform{1.f};
|
||||
};
|
||||
|
||||
ModelRenderSystem(const ModelRenderSystem&) = delete;
|
||||
@@ -25,7 +31,7 @@ class ModelRenderSystem {
|
||||
~ModelRenderSystem();
|
||||
|
||||
void render(vk::CommandBuffer commandBuffer,
|
||||
std::span<const std::unique_ptr<Mesh>> meshes,
|
||||
std::span<const MeshInstance> instances,
|
||||
const FrameInfo& frameInfo);
|
||||
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user