Files
cup_edit/ios/src/DependencyGraph.h
2022-02-06 13:28:28 +08:00

123 lines
4.4 KiB
C++

/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef GLTFIO_DEPENDENCY_GRAPH_H
#define GLTFIO_DEPENDENCY_GRAPH_H
#include <utils/Entity.h>
#include <tsl/robin_map.h>
#include <tsl/robin_set.h>
#include <queue>
#include <string>
namespace filament {
class MaterialInstance;
class Texture;
}
namespace gltfio {
/**
* Internal graph that enables FilamentAsset to discover "ready-to-render" entities by tracking
* the loading status of Texture objects that each entity depends on.
*
* Renderables connect to a set of material instances, which in turn connect to a set of parameter
* names, which in turn connect to a set of texture objects. These relationships are not easily
* inspectable using the Filament API or ECS.
*
* One graph corresponds to a single glTF asset. The graph only contains weak references, it does
* not have ownership over any Filament objects. Here's an example:
*
* Entity Entity Entity Entity
* | / \ | /
* | / \ | /
* Material Material Material
* / | \ |
* / | \ |
* Param Param Param Param
* \ / | |
* \ / | |
* Texture Texture Texture
*
* Note that the left-most entity in the above graph has no textures, so it becomes ready as soon as
* finalize is called.
*/
class DependencyGraph {
public:
using Material = filament::MaterialInstance;
using Entity = utils::Entity;
// Pops up to "count" ready-to-render entities off the queue.
// If "result" is non-null, returns the number of written items.
// If "result" is null, returns the number of available entities.
size_t popRenderables(Entity* result, size_t count) noexcept;
// These are called during the initial asset loader phase.
void addEdge(Entity entity, Material* material);
void addEdge(Material* material, const char* parameter);
// This is called at the end of the initial asset loading phase.
// Makes a guarantee that no new material nodes or parameter nodes will be added to the graph.
void finalize();
// This can be called after finalization to allow for dynamic addition of entities.
// It is slower than finalize() because it checks the readiness of existing materials.
void refinalize();
// These are called after textures have created and decoded.
void addEdge(filament::Texture* texture, Material* material, const char* parameter);
void markAsReady(filament::Texture* texture);
private:
struct TextureNode {
filament::Texture* texture;
bool ready;
};
struct MaterialNode {
tsl::robin_map<std::string, TextureNode*> params;
};
struct EntityNode {
tsl::robin_set<Material*> materials;
size_t numReadyMaterials = 0;
};
void checkReadiness(Material* material);
void markAsReady(Material* material);
TextureNode* getStatus(filament::Texture* texture);
// The following maps contain the directed edges in the graph.
tsl::robin_map<Entity, EntityNode> mEntityToMaterial;
tsl::robin_map<Material*, tsl::robin_set<Entity>> mMaterialToEntity;
tsl::robin_map<Material*, MaterialNode> mMaterialToTexture;
tsl::robin_map<filament::Texture*, tsl::robin_set<Material*>> mTextureToMaterial;
// Each texture (and its readiness flag) can be referenced from multiple nodes, so we own
// a collection of wrapper objects in the following map. This uses std::unique_ptr to allow
// nodes to refer to a texture wrapper using a stable weak pointer.
tsl::robin_map<filament::Texture*, std::unique_ptr<TextureNode>> mTextureNodes;
std::queue<Entity> mReadyRenderables;
bool mFinalized = false;
};
} // namespace gltfio
#endif // GLTFIO_DEPENDENCY_GRAPH_H