1#include "MeshManager.h"
5#include "Platform/Instrumentation.h"
7#include "Renderer/IRenderer.h"
8#include "Renderer/Renderer.h"
9#include "Renderer/RenderMesh.h"
10#include "Resources/BufferManager.h"
12#include "Rendering/ICapabilities.h"
14#include "Foundation/Logging/Logger.h"
15#include "Foundation/Platform/Timer.h"
24 void generateCube(
Mesh * mesh,
float size = 1.0f)
70 mesh->
setPositions(
reinterpret_cast<glm::vec3 *
>(vertexes),
reinterpret_cast<glm::vec3 *
>(vertexes) + 36);
116 mesh->
setNormals(
reinterpret_cast<glm::vec3 *
>(normals),
reinterpret_cast<glm::vec3 *
>(normals) + 36);
118 float texCoords[] = {
162 mesh->
setTexCoords(
reinterpret_cast<glm::vec2 *
>(texCoords),
reinterpret_cast<glm::vec2 *
>(texCoords) + 36);
178 bool updateAsync =
false;
181 std::vector<UpdatedMesh> updatedMeshes;
185 Mesh * mesh =
nullptr;
194 std::vector<Deletion> deletionQueue;
195 std::vector<Swapped> swappedQueue;
196 std::deque<Cogs::Core::MeshManager::SwapOperation> swappingResources;
207 context->taskManager->wait(data->meshGroup);
209 context->taskManager->wait(data->meshGroup);
215 ResourceManager::initialize();
216 VertexFormats::initialize();
218 auto mesh = create();
220 defaultResource = mesh;
222 generateCube(mesh.resolve(), 0.5f);
224 setResourceId(mesh.get(), getNextResourceId());
229 return getByName(name);
234 loadInfo->
handle->setChanged();
235 setProcessed(loadInfo);
240 if (!data->updateAsync) {
241 context->renderer->getResources()->releaseResource(mesh);
245void Cogs::Core::MeshManager::destroyInternal(
ResourceBase * resource)
247 if (!data->updateAsync) {
248 ResourceManager::destroyInternal(resource);
254 return context->bufferManager->create();
259 if (!context->device->getCapabilities()->getDeviceCapabilities().SupportsMultipleThreads || !context->variables->get(
"resources.meshes.updateAsync",
false)) {
260 ResourceManager::processDeletion();
264 CpuInstrumentationScope(SCOPE_RESOURCES,
"MeshManager::processDeletion");
266 data->updateAsync = context->variables->get(
"resources.meshes.updateAsync",
false);
268 auto t = Timer::startNew();
270 if (data->updateAsync) {
271 std::vector<ResourceBase *> deletion;
272 fillDeletionQueue(deletion);
274 data->deletionQueue.reserve(deletion.size());
276 for (
auto & d : deletion) {
277 auto mesh = (
Mesh *)d;
281 ResourceManager::processDeletion();
284 if (data->deletionQueue.size()) {
285 context->taskManager->enqueueChild(data->meshGroup, [
this, deletionQueue = std::move(data->deletionQueue)]()
mutable
287 CpuInstrumentationScope(SCOPE_RESOURCES,
"MeshManager::processDeletionTask");
289 Renderer * renderer = dynamic_cast<Cogs::Core::Renderer*>(context->renderer);
291 for (auto & deletion : deletionQueue) {
292 if (!deletion.attachment) continue;
293 auto renderMesh = (RenderMesh *)deletion.attachment;
294 renderMesh->release(renderer);
295 renderer->getRenderResources().destroyRenderMesh(renderMesh);
296 deletion.mesh->attachResource(nullptr);
299 for (
auto & deletion : deletionQueue) {
300 safeDestroy(deletion.mesh);
301 destroyLocked(deletion.mesh);
306 if (data->swappedQueue.size()) {
307 context->taskManager->enqueueChild(data->meshGroup, [
this, swappedQueue = std::move(data->swappedQueue)]()
309 CpuInstrumentationScope(SCOPE_RESOURCES,
"MeshManager::processSwappedMeshTask");
313 for (
auto & swapped : swappedQueue) {
314 if (!swapped.attachment)
continue;
315 auto renderMesh = (
RenderMesh *)swapped.attachment;
316 renderMesh->release(renderer);
317 renderer->getRenderResources().destroyRenderMesh(renderMesh);
322 auto elapsed = t.elapsedSeconds();
324 if (elapsed > 0.005) {
325 LOG_DEBUG(logger,
"MeshManager::processDeletion elapsed: %f", elapsed);
331 if (!context->device->getCapabilities()->getDeviceCapabilities().SupportsMultipleThreads || !context->variables->get(
"resources.meshes.updateAsync",
false)) {
336 bool isBatch = !context->variables->get(
"editor.batch")->getValue().empty();
338 float uploadBatchMaxTime = context->variables->get(
"resources.meshes.uploadBatchMaxTime", 0.f);
340 LockGuard swapLock(swapMutex);
342 auto context = this->context;
346 for (
auto & updatedMesh : data->updatedMeshes) {
347 auto mesh = updatedMesh.mesh.resolve();
354 *mesh = std::move(updatedMesh.proxy);
357 updatedMesh.renderMesh->setResource(mesh);
366 data->updatedMeshes.clear();
368 for (Cogs::Core::MeshManager::SwapOperation& resource : swapQueue) {
369 data->swappingResources.push_back(std::move(resource));
372 if (data->swappingResources.empty()) {
377 context->taskManager->enqueueChild(data->meshGroup, [context, data = this->data.get(), isBatch, uploadBatchMaxTime]()
mutable
379 CpuInstrumentationScope(SCOPE_RESOURCES,
"MeshManager::asyncUpdate");
381 auto t = Timer::startNew();
382 while(!data->swappingResources.empty()) {
383 Cogs::Core::MeshManager::SwapOperation swapResource = std::move(data->swappingResources.front());
384 data->swappingResources.pop_front();
386 Renderer * renderer = dynamic_cast<Cogs::Core::Renderer*>(context->renderer);
387 auto & renderResources = renderer->getRenderResources();
389 auto & updatedMesh = data->updatedMeshes.emplace_back();
392 auto renderMesh = renderResources.createRenderMesh();
394 renderMesh->update(swapResource.source.resolve(), renderer->getDevice(), &renderResources);
396 updatedMesh.renderMesh = renderMesh;
399 updatedMesh.mesh = swapResource.destinationHandle;
400 updatedMesh.proxy = std::move(*swapResource.source.resolve());
402 if (!isBatch && 0.0 < uploadBatchMaxTime && uploadBatchMaxTime < t.elapsedSeconds()) {
408 LOG_TRACE(logger,
"Async mesh processing elapsed: %f", t.elapsedSeconds());
412 context->engine->setDirty();
419 return context->renderer->getResources()->updateResource(meshHandle);
A Context instance contains all the services, systems and runtime components needed to use Cogs.
std::unique_ptr< class TaskManager > taskManager
TaskManager service instance.
void processDeletion() override
Process resources pending deallocation.
ActivationResult handleActivation(ResourceHandle handle, Mesh *mesh) override
Overridden to handle mesh activation, updating the resource in the renderer.
void handleLoad(ResourceLoadInfoBase *loadInfo) override
Handler for resource loading.
void initialize() override
MeshManager(Context *context)
Constructs a MeshManager in the given context.
void handleDeletion(Mesh *mesh) override
Overridden to handle mesh deletion, removing the resource from the renderer.
~MeshManager() override
Destructs the MeshManager.
void processSwapping() override
Overridden to dispatch async updates for swapping resources if enabled.
The generic resource manager provides a base implementation for specialized resource managers to buil...
void processSwapping() override
Process queued swap operations, exchanging resource contents of the destination resources by those in...
static constexpr TaskQueueId ResourceQueue
Resource task queue.
Log implementation class.
Provides a weakly referenced view over the contents of a string.
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
ActivationResult
Defines results for resource activation.
Contains geometry calculations and generation.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Meshes contain streams of vertex data in addition to index data and options defining geometry used fo...
void setTexCoords(std::span< const glm::vec2 > texCoords)
Set the texture coordinate data of the Mesh.
void setNormals(std::span< const glm::vec3 > normals)
Set the normal data of the Mesh.
void setPositions(std::span< const glm::vec3 > positions)
Set the position data of the Mesh.
Base class for engine resources.
void incrementGeneration()
Increment the generation count.
void attachResource(RenderResource *attachment)
Attach the given GPU resource to the resource.
RenderResource * getAttachedResource() const
Get the attached resource.
bool hasAttachedResource() const
Check if the resource has an attachment.
ResourceHandleBase handle
Handle to resource structure for holding actual resource data.
Task id struct used to identify unique Task instances.