no message
This commit is contained in:
164
cocos/renderer/pipeline/custom/details/DebugUtils.h
Normal file
164
cocos/renderer/pipeline/custom/details/DebugUtils.h
Normal file
@@ -0,0 +1,164 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <sstream>
|
||||
#include <string_view>
|
||||
#include "cocos/base/std/container/string.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace render {
|
||||
|
||||
template <class String>
|
||||
class Indent {
|
||||
public:
|
||||
explicit Indent(String& indent)
|
||||
: mIndent(&indent) {
|
||||
mIndent->append(" ");
|
||||
}
|
||||
~Indent() {
|
||||
reset();
|
||||
}
|
||||
Indent(Indent&& rhs) noexcept
|
||||
: mIndent(rhs.mIndent) {
|
||||
rhs.mIndent = nullptr;
|
||||
}
|
||||
Indent& operator=(Indent&& rhs) noexcept {
|
||||
mIndent = rhs.mIndent;
|
||||
rhs.mIndent = nullptr;
|
||||
return *this;
|
||||
}
|
||||
void reset() {
|
||||
if (mIndent) {
|
||||
mIndent->erase(mIndent->size() - 4);
|
||||
mIndent = nullptr;
|
||||
}
|
||||
}
|
||||
String* mIndent = nullptr;
|
||||
};
|
||||
|
||||
inline void indent(ccstd::string& str) {
|
||||
str.append(" ");
|
||||
}
|
||||
|
||||
inline void indent(ccstd::pmr::string& str) {
|
||||
str.append(" ");
|
||||
}
|
||||
|
||||
inline void unindent(ccstd::string& str) noexcept {
|
||||
auto sz = str.size() < static_cast<size_t>(4) ? str.size() : static_cast<size_t>(4);
|
||||
str.erase(str.size() - sz);
|
||||
}
|
||||
|
||||
inline void unindent(ccstd::pmr::string& str) noexcept {
|
||||
auto sz = str.size() < static_cast<size_t>(4) ? str.size() : static_cast<size_t>(4);
|
||||
str.erase(str.size() - sz);
|
||||
}
|
||||
|
||||
inline void copyString(
|
||||
std::ostream& os,
|
||||
std::string_view space, std::string_view str, // NOLINT(bugprone-easily-swappable-parameters)
|
||||
bool append = false) {
|
||||
std::istringstream iss{ccstd::string(str)};
|
||||
ccstd::string line;
|
||||
int count = 0;
|
||||
while (std::getline(iss, line)) {
|
||||
if (line.empty()) {
|
||||
os << '\n';
|
||||
} else if (line[0] == '#') {
|
||||
os << line << '\n';
|
||||
} else {
|
||||
if (append) {
|
||||
if (count == 0) {
|
||||
os << line;
|
||||
} else {
|
||||
os << '\n'
|
||||
<< space << line;
|
||||
}
|
||||
} else {
|
||||
os << space << line << '\n';
|
||||
}
|
||||
}
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
inline void copyString(std::ostream& os, std::string_view str) {
|
||||
std::istringstream iss{ccstd::string(str)};
|
||||
ccstd::string line;
|
||||
while (std::getline(iss, line)) {
|
||||
if (line.empty()) {
|
||||
os << '\n';
|
||||
} else {
|
||||
os << line << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void copyCppString(
|
||||
std::ostream& os,
|
||||
std::string_view space, std::string_view str, // NOLINT(bugprone-easily-swappable-parameters)
|
||||
bool append = false) {
|
||||
std::istringstream iss{ccstd::string(str)};
|
||||
ccstd::string line;
|
||||
int count = 0;
|
||||
while (std::getline(iss, line)) {
|
||||
if (line.empty()) {
|
||||
os << '\n';
|
||||
} else if (line[0] == '#') {
|
||||
os << line << '\n';
|
||||
} else if (*line.rbegin() == ':') {
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1920
|
||||
os << space << line << '\n';
|
||||
#else
|
||||
os << space.substr(0, std::max(static_cast<size_t>(4), space.size()) - 4) << line << "\n";
|
||||
#endif
|
||||
} else {
|
||||
if (append) {
|
||||
if (count == 0) {
|
||||
os << line;
|
||||
} else {
|
||||
os << '\n'
|
||||
<< space << line;
|
||||
}
|
||||
} else {
|
||||
os << space << line << '\n';
|
||||
}
|
||||
}
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace render
|
||||
|
||||
} // namespace cc
|
||||
|
||||
#define OSS oss << space
|
||||
|
||||
#define INDENT(...) Indent<std::remove_reference_t<decltype(space)>> ind_##__VA_ARGS__(space)
|
||||
#define UNINDENT(...) ind_##__VA_ARGS__.reset()
|
||||
|
||||
#define INDENT_BEG() space.append(" ")
|
||||
#define INDENT_END() space.erase(std::max(space.size(), size_t(4)) - 4)
|
||||
678
cocos/renderer/pipeline/custom/details/GraphImpl.h
Normal file
678
cocos/renderer/pipeline/custom/details/GraphImpl.h
Normal file
@@ -0,0 +1,678 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <boost/graph/adjacency_iterator.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
#include <boost/iterator/iterator_adaptor.hpp>
|
||||
#include <functional>
|
||||
#include "cocos/base/std/container/vector.h"
|
||||
#include "cocos/base/std/variant.h"
|
||||
#include "cocos/renderer/pipeline/custom/details/GraphTypes.h"
|
||||
#include "cocos/renderer/pipeline/custom/details/GslUtils.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace render {
|
||||
|
||||
namespace impl {
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// PropertyMap
|
||||
//--------------------------------------------------------------------
|
||||
template <class Category, class Graph, class Value, class Reference>
|
||||
struct VectorVertexBundlePropertyMap
|
||||
: public boost::put_get_helper<
|
||||
Reference, VectorVertexBundlePropertyMap<Category, Graph, Value, Reference>> {
|
||||
using value_type = Value;
|
||||
using reference = Reference;
|
||||
using key_type = typename Graph::vertex_descriptor;
|
||||
using category = Category;
|
||||
|
||||
VectorVertexBundlePropertyMap(Graph &g) noexcept // NOLINT(google-explicit-constructor)
|
||||
: graph(&g) {}
|
||||
|
||||
inline reference operator[](const key_type &v) const noexcept {
|
||||
return graph->mVertices[v].property;
|
||||
}
|
||||
inline reference operator()(const key_type &v) const noexcept {
|
||||
return operator[](v);
|
||||
}
|
||||
|
||||
Graph *graph{};
|
||||
};
|
||||
|
||||
template <class Category, class Graph, class Value, class Reference>
|
||||
struct PointerVertexBundlePropertyMap
|
||||
: public boost::put_get_helper<
|
||||
Reference, PointerVertexBundlePropertyMap<Category, Graph, Value, Reference>> {
|
||||
using value_type = Value;
|
||||
using reference = Reference;
|
||||
using key_type = typename Graph::vertex_descriptor;
|
||||
using category = Category;
|
||||
|
||||
PointerVertexBundlePropertyMap(Graph &g) noexcept // NOLINT(google-explicit-constructor)
|
||||
: graph(&g) {}
|
||||
|
||||
inline reference operator[](const key_type &v) const noexcept {
|
||||
auto *sv = static_cast<typename Graph::vertex_type *>(v);
|
||||
return sv->property;
|
||||
}
|
||||
inline reference operator()(const key_type &v) const noexcept {
|
||||
return operator[](v);
|
||||
}
|
||||
|
||||
Graph *graph{};
|
||||
};
|
||||
|
||||
template <class Category, class Graph, class Value, class Reference, class MemberPointer>
|
||||
struct VectorVertexBundleMemberPropertyMap
|
||||
: public boost::put_get_helper<
|
||||
Reference, VectorVertexBundleMemberPropertyMap<Category, Graph, Value, Reference, MemberPointer>> {
|
||||
using value_type = Value;
|
||||
using reference = Reference;
|
||||
using key_type = typename Graph::vertex_descriptor;
|
||||
using category = Category;
|
||||
|
||||
VectorVertexBundleMemberPropertyMap(Graph &g, MemberPointer ptr) noexcept
|
||||
: graph(&g), memberPointer(ptr) {}
|
||||
|
||||
inline reference operator[](const key_type &v) const noexcept {
|
||||
return graph->mVertices[v].property.*memberPointer;
|
||||
}
|
||||
inline reference operator()(const key_type &v) const noexcept {
|
||||
return operator[](v);
|
||||
}
|
||||
|
||||
Graph *graph{};
|
||||
MemberPointer memberPointer{};
|
||||
};
|
||||
|
||||
template <class Category, class Graph, class Value, class Reference, class MemberPointer>
|
||||
struct PointerVertexBundleMemberPropertyMap
|
||||
: public boost::put_get_helper<
|
||||
Reference, PointerVertexBundleMemberPropertyMap<Category, Graph, Value, Reference, MemberPointer>> {
|
||||
using value_type = Value;
|
||||
using reference = Reference;
|
||||
using key_type = typename Graph::vertex_descriptor;
|
||||
using category = Category;
|
||||
|
||||
PointerVertexBundleMemberPropertyMap(Graph &g, MemberPointer ptr) noexcept
|
||||
: graph(&g), memberPointer(ptr) {}
|
||||
|
||||
inline reference operator[](const key_type &v) const noexcept {
|
||||
auto *sv = static_cast<typename Graph::vertex_type *>(v);
|
||||
return sv->property.*memberPointer;
|
||||
}
|
||||
inline reference operator()(const key_type &v) const noexcept {
|
||||
return operator[](v);
|
||||
}
|
||||
|
||||
Graph *graph{};
|
||||
MemberPointer memberPointer{};
|
||||
};
|
||||
|
||||
template <class Category, class Graph, class Container, class Value, class Reference>
|
||||
struct VectorVertexComponentPropertyMap
|
||||
: public boost::put_get_helper<
|
||||
Reference, VectorVertexComponentPropertyMap<Category, Graph, Container, Value, Reference>> {
|
||||
using value_type = Value;
|
||||
using reference = Reference;
|
||||
using key_type = typename Graph::vertex_descriptor;
|
||||
using category = Category;
|
||||
|
||||
VectorVertexComponentPropertyMap(Container &c) noexcept // NOLINT(google-explicit-constructor)
|
||||
: container(&c) {}
|
||||
|
||||
inline reference operator[](const key_type &v) const noexcept {
|
||||
return (*container)[v];
|
||||
}
|
||||
inline reference operator()(const key_type &v) const noexcept {
|
||||
return operator[](v);
|
||||
}
|
||||
|
||||
Container *container{};
|
||||
};
|
||||
|
||||
template <class Category, class Graph, class Container, class Value, class Reference, class MemberPointer>
|
||||
struct VectorVertexComponentMemberPropertyMap
|
||||
: public boost::put_get_helper<
|
||||
Reference, VectorVertexComponentMemberPropertyMap<Category, Graph, Container, Value, Reference, MemberPointer>> {
|
||||
using value_type = Value;
|
||||
using reference = Reference;
|
||||
using key_type = typename Graph::vertex_descriptor;
|
||||
using category = Category;
|
||||
|
||||
VectorVertexComponentMemberPropertyMap(Container &c, MemberPointer ptr) noexcept
|
||||
: container(&c), memberPointer(ptr) {}
|
||||
|
||||
inline reference operator[](const key_type &v) const noexcept {
|
||||
return (*container)[v].*memberPointer;
|
||||
}
|
||||
inline reference operator()(const key_type &v) const noexcept {
|
||||
return operator[](v);
|
||||
}
|
||||
|
||||
Container *container{};
|
||||
MemberPointer memberPointer{};
|
||||
};
|
||||
|
||||
template <class Category, class Graph, class ComponentPointer, class Value, class Reference>
|
||||
struct VectorVertexIteratorComponentPropertyMap
|
||||
: public boost::put_get_helper<
|
||||
Reference, VectorVertexIteratorComponentPropertyMap<Category, Graph, ComponentPointer, Value, Reference>> {
|
||||
using value_type = Value;
|
||||
using reference = Reference;
|
||||
using key_type = typename Graph::vertex_descriptor;
|
||||
using category = Category;
|
||||
|
||||
VectorVertexIteratorComponentPropertyMap(Graph &g, ComponentPointer component) noexcept
|
||||
: graph(&g), componentPointer(component) {}
|
||||
|
||||
inline reference operator[](const key_type &v) const noexcept {
|
||||
return *(graph->mVertices[v].*componentPointer);
|
||||
}
|
||||
inline reference operator()(const key_type &v) const noexcept {
|
||||
return operator[](v);
|
||||
}
|
||||
|
||||
Graph *graph{};
|
||||
ComponentPointer componentPointer{};
|
||||
};
|
||||
|
||||
template <class Category, class Graph, class ComponentPointer, class Value, class Reference, class MemberPointer>
|
||||
struct VectorVertexIteratorComponentMemberPropertyMap
|
||||
: public boost::put_get_helper<
|
||||
Reference, VectorVertexIteratorComponentMemberPropertyMap<Category, Graph, ComponentPointer, Value, Reference, MemberPointer>> {
|
||||
using value_type = Value;
|
||||
using reference = Reference;
|
||||
using key_type = typename Graph::vertex_descriptor;
|
||||
using category = Category;
|
||||
|
||||
VectorVertexIteratorComponentMemberPropertyMap(Graph &g, ComponentPointer component, MemberPointer ptr) noexcept
|
||||
: graph(&g), componentPointer(component), memberPointer(ptr) {}
|
||||
|
||||
inline reference operator[](const key_type &v) const noexcept {
|
||||
return (*(graph->mVertices[v].*componentPointer)).*memberPointer;
|
||||
}
|
||||
inline reference operator()(const key_type &v) const noexcept {
|
||||
return operator[](v);
|
||||
}
|
||||
|
||||
Graph *graph{};
|
||||
ComponentPointer componentPointer{};
|
||||
MemberPointer memberPointer{};
|
||||
};
|
||||
|
||||
template <class Category, class VertexDescriptor, class Container, class Value, class Reference>
|
||||
struct VectorPathPropertyMap
|
||||
: public boost::put_get_helper<
|
||||
Reference, VectorPathPropertyMap<Category, VertexDescriptor, Container, Value, Reference>> {
|
||||
using value_type = Value;
|
||||
using reference = Reference;
|
||||
using key_type = VertexDescriptor;
|
||||
using category = Category;
|
||||
|
||||
VectorPathPropertyMap(Container &c) noexcept // NOLINT(google-explicit-constructor)
|
||||
: container(&c) {}
|
||||
|
||||
inline reference operator[](const key_type &v) const noexcept {
|
||||
return (*container)[v].mPathIterator->first;
|
||||
}
|
||||
inline reference operator()(const key_type &v) const noexcept {
|
||||
return operator[](v);
|
||||
}
|
||||
|
||||
Container *container{};
|
||||
};
|
||||
|
||||
template <class Category, class Graph, class Value, class Reference>
|
||||
struct EdgeBundlePropertyMap
|
||||
: public boost::put_get_helper<
|
||||
Reference, EdgeBundlePropertyMap<Category, Graph, Value, Reference>> {
|
||||
using value_type = Value;
|
||||
using reference = Reference;
|
||||
using key_type = typename Graph::edge_descriptor;
|
||||
using category = Category;
|
||||
|
||||
EdgeBundlePropertyMap(Graph &g) noexcept // NOLINT(google-explicit-constructor)
|
||||
: graph(&g) {}
|
||||
|
||||
inline reference operator[](const key_type &e) const noexcept {
|
||||
return *static_cast<typename Graph::edge_property_type *>(e.get_property());
|
||||
}
|
||||
inline reference operator()(const key_type &e) const noexcept {
|
||||
return operator[](e);
|
||||
}
|
||||
|
||||
Graph *graph{};
|
||||
};
|
||||
|
||||
template <class Category, class Graph, class Value, class Reference, class MemberPointer>
|
||||
struct EdgeBundleMemberPropertyMap
|
||||
: public boost::put_get_helper<
|
||||
Reference, EdgeBundleMemberPropertyMap<Category, Graph, Value, Reference, MemberPointer>> {
|
||||
using value_type = Value;
|
||||
using reference = Reference;
|
||||
using key_type = typename Graph::edge_descriptor;
|
||||
using category = Category;
|
||||
|
||||
EdgeBundleMemberPropertyMap(Graph &g, MemberPointer ptr) noexcept
|
||||
: graph(&g), memberPointer(ptr) {}
|
||||
|
||||
inline reference operator[](const key_type &e) const noexcept {
|
||||
auto &p = *static_cast<typename Graph::edge_property_type *>(e.get_property());
|
||||
return p.*memberPointer;
|
||||
}
|
||||
inline reference operator()(const key_type &e) const noexcept {
|
||||
return operator[](e);
|
||||
}
|
||||
|
||||
Graph *graph{};
|
||||
MemberPointer memberPointer{};
|
||||
};
|
||||
|
||||
template <class Sequence, class Predicate>
|
||||
void sequenceEraseIf(Sequence &c, Predicate &&p) noexcept {
|
||||
if (!c.empty()) {
|
||||
c.erase(std::remove_if(c.begin(), c.end(), p), c.end());
|
||||
}
|
||||
}
|
||||
|
||||
// notice: Predicate might be different from associative key
|
||||
// when Predicate is associative key, it is slower than erase [lower_bound, upper_bound)
|
||||
template <class AssociativeContainer, class Predicate>
|
||||
void associativeEraseIf(AssociativeContainer &c, Predicate &&p) noexcept {
|
||||
auto next = c.begin();
|
||||
for (auto i = next; next != c.end(); i = next) {
|
||||
++next;
|
||||
if (p(*i)) {
|
||||
c.erase(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// notice: Predicate might be different from associative key
|
||||
// when Predicate is associative key, it is slower than erase [lower_bound, upper_bound)
|
||||
template <class AssociativeContainer, class Predicate>
|
||||
void unstableAssociativeEraseIf(AssociativeContainer &c, Predicate &&p) noexcept {
|
||||
auto n = c.size();
|
||||
while (n--) {
|
||||
for (auto i = c.begin(); i != c.end(); ++i) {
|
||||
if (p(*i)) {
|
||||
c.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class EdgeDescriptor, class IncidenceList>
|
||||
inline void removeIncidenceEdge(EdgeDescriptor e, IncidenceList &el) noexcept {
|
||||
e.expectsNoProperty();
|
||||
for (auto i = el.begin(); i != el.end(); ++i) {
|
||||
if ((*i).get_target() == e.target) {
|
||||
el.erase(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class DirectedCategory, class VertexDescriptor, class IncidenceList, class EdgeProperty>
|
||||
inline void removeIncidenceEdge(
|
||||
EdgeDescriptorWithProperty<DirectedCategory, VertexDescriptor> e, IncidenceList &el) noexcept {
|
||||
for (auto i = el.begin(); i != el.end(); ++i) {
|
||||
if (static_cast<void *>(&(*i).get_property()) == e.get_property()) {
|
||||
el.erase(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class Graph, class IncidenceList, class VertexDescriptor>
|
||||
inline void removeDirectedAllEdgeProperties(Graph &g, IncidenceList &el, VertexDescriptor v) noexcept {
|
||||
auto i = el.begin();
|
||||
auto end = el.end();
|
||||
for (; i != end; ++i) {
|
||||
if ((*i).get_target() == v) {
|
||||
// NOTE: Wihtout this skip, this loop will double-delete
|
||||
// properties of loop edges. This solution is based on the
|
||||
// observation that the incidence edges of a vertex with a loop
|
||||
// are adjacent in the out edge list. This *may* actually hold
|
||||
// for multisets also.
|
||||
bool skip = (std::next(i) != end && i->get_iter() == std::next(i)->get_iter());
|
||||
g.edges.erase((*i).get_iter());
|
||||
if (skip) {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class IncidenceIterator, class IncidenceList, class Predicate>
|
||||
inline void sequenceRemoveIncidenceEdgeIf(IncidenceIterator first, IncidenceIterator last,
|
||||
IncidenceList &el, Predicate &&pred) noexcept {
|
||||
// remove_if
|
||||
while (first != last && !pred(*first)) {
|
||||
++first;
|
||||
}
|
||||
auto i = first;
|
||||
if (first != last) {
|
||||
for (++i; i != last; ++i) {
|
||||
if (!pred(*i)) {
|
||||
*first.base() = std::move(*i.base());
|
||||
++first;
|
||||
}
|
||||
}
|
||||
}
|
||||
el.erase(first.base(), el.end());
|
||||
}
|
||||
|
||||
template <class IncidenceIterator, class IncidenceList, class Predicate>
|
||||
inline void associativeRemoveIncidenceEdgeIf(IncidenceIterator first, IncidenceIterator last,
|
||||
IncidenceList &el, Predicate &&pred) noexcept {
|
||||
for (auto next = first; first != last; first = next) {
|
||||
++next;
|
||||
if (pred(*first)) {
|
||||
el.erase(first.base());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class Graph, class EdgeDescriptor, class EdgeProperty>
|
||||
inline void removeUndirectedEdge(Graph &g, EdgeDescriptor e, EdgeProperty &p) noexcept {
|
||||
auto &outEdgeList = g.getOutEdgeList(source(e, g));
|
||||
auto outEdgeIter = outEdgeList.begin();
|
||||
decltype((*outEdgeIter).get_iter()) edgeIterToErase;
|
||||
for (; outEdgeIter != outEdgeList.end(); ++outEdgeIter) {
|
||||
if (&(*outEdgeIter).get_property() == &p) {
|
||||
edgeIterToErase = (*outEdgeIter).get_iter();
|
||||
outEdgeList.erase(outEdgeIter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto &inEdgeList = g.getOutEdgeList(target(e, g));
|
||||
auto inEdgeIter = inEdgeList.begin();
|
||||
for (; inEdgeIter != inEdgeList.end(); ++inEdgeIter) {
|
||||
if (&(*inEdgeIter).get_property() == &p) {
|
||||
inEdgeList.erase(inEdgeIter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
g.edges.erase(edgeIterToErase);
|
||||
}
|
||||
|
||||
template <class Graph, class IncidenceIterator, class IncidenceList, class Predicate>
|
||||
inline void sequenceRemoveUndirectedOutEdgeIf(Graph &g,
|
||||
IncidenceIterator first, IncidenceIterator last, IncidenceList &el,
|
||||
Predicate &&pred) noexcept {
|
||||
// remove_if
|
||||
while (first != last && !pred(*first)) {
|
||||
++first;
|
||||
}
|
||||
auto i = first;
|
||||
bool selfLoopRemoved = false;
|
||||
if (first != last) {
|
||||
for (; i != last; ++i) {
|
||||
if (selfLoopRemoved) {
|
||||
/* With self loops, the descriptor will show up
|
||||
* twice. The first time it will be removed, and now it
|
||||
* will be skipped.
|
||||
*/
|
||||
selfLoopRemoved = false;
|
||||
} else if (!pred(*i)) {
|
||||
*first.base() = std::move(*i.base());
|
||||
++first;
|
||||
} else {
|
||||
if (source(*i, g) == target(*i, g)) {
|
||||
selfLoopRemoved = true;
|
||||
} else {
|
||||
// Remove the edge from the target
|
||||
removeIncidenceEdge(*i, g.getOutEdgeList(target(*i, g)));
|
||||
}
|
||||
|
||||
// Erase the edge property
|
||||
g.edges.erase((*i.base()).get_iter());
|
||||
}
|
||||
}
|
||||
}
|
||||
el.erase(first.base(), el.end());
|
||||
}
|
||||
|
||||
template <class Graph, class IncidenceIterator, class IncidenceList, class Predicate>
|
||||
inline void associativeRemoveUndirectedOutEdgeIf(Graph &g,
|
||||
IncidenceIterator first, IncidenceIterator last, IncidenceList &el,
|
||||
Predicate &&pred) noexcept {
|
||||
for (auto next = first; first != last; first = next) {
|
||||
++next;
|
||||
if (pred(*first)) {
|
||||
if (source(*first, g) != target(*first, g)) {
|
||||
// Remove the edge from the target
|
||||
removeIncidenceEdge(*first, g.getOutEdgeList(target(*first, g)));
|
||||
}
|
||||
|
||||
// Erase the edge property
|
||||
g.edges.erase((*first.base()).get_iter());
|
||||
|
||||
// Erase the edge in the source
|
||||
el.erase(first.base());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// list/vector out_edge_list
|
||||
template <class IncidenceList, class VertexDescriptor>
|
||||
inline void reindexEdgeList(IncidenceList &el, VertexDescriptor u) {
|
||||
auto ei = el.begin();
|
||||
auto eEnd = el.end();
|
||||
for (; ei != eEnd; ++ei) {
|
||||
if ((*ei).get_target() > u) {
|
||||
--(*ei).get_target();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class Tag, class Container, class HandleDescriptor>
|
||||
inline void reindexVectorHandle(Container &container, HandleDescriptor u) {
|
||||
static_assert(std::is_arithmetic<HandleDescriptor>::value, "reindexVectorHandle");
|
||||
|
||||
using handle_type = ValueHandle<Tag, HandleDescriptor>;
|
||||
for (auto &vert : container) {
|
||||
if (ccstd::holds_alternative<handle_type>(vert.handle)) {
|
||||
auto &v = ccstd::get<handle_type>(vert.handle).value;
|
||||
if (v > u) {
|
||||
--v;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class Graph, class VertexDescriptor>
|
||||
inline void removeVectorVertex(Graph &g, VertexDescriptor u, boost::directed_tag /*tag*/) {
|
||||
g._vertices.erase(g._vertices.begin() + u);
|
||||
auto numV = num_vertices(g);
|
||||
if (u != numV) {
|
||||
for (VertexDescriptor v = 0; v < numV; ++v) {
|
||||
reindexEdgeList(g.getOutEdgeList(v), u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class Graph, class VertexDescriptor>
|
||||
inline void removeVectorVertex(Graph &g, VertexDescriptor u, boost::undirected_tag /*tag*/) {
|
||||
g._vertices.erase(g._vertices.begin() + u);
|
||||
VertexDescriptor numV = num_vertices(g);
|
||||
for (VertexDescriptor v = 0; v < numV; ++v) {
|
||||
reindexEdgeList(g.getOutEdgeList(v), u);
|
||||
}
|
||||
|
||||
auto ei = g.edges.begin();
|
||||
auto eiEnd = g.edges.end();
|
||||
for (; ei != eiEnd; ++ei) {
|
||||
if (ei->source > u) {
|
||||
--ei->source;
|
||||
}
|
||||
if (ei->target > u) {
|
||||
--ei->target;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class Graph, class VertexDescriptor>
|
||||
inline void removeVectorVertex(Graph &g, VertexDescriptor u, boost::bidirectional_tag /*tag*/) {
|
||||
g._vertices.erase(g._vertices.begin() + u);
|
||||
VertexDescriptor numV = num_vertices(g);
|
||||
VertexDescriptor v;
|
||||
if (u != numV) {
|
||||
for (v = 0; v < numV; ++v) {
|
||||
reindexEdgeList(g.getOutEdgeList(v), u);
|
||||
}
|
||||
|
||||
for (v = 0; v < numV; ++v) {
|
||||
reindexEdgeList(g.getInEdgeList(v), u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class Graph, class VertexDescriptor, class EdgeList>
|
||||
inline void removeVectorVertex(Graph &g, EdgeList & /*edges*/,
|
||||
VertexDescriptor u, boost::bidirectional_tag /*tag*/) {
|
||||
g._vertices.erase(g._vertices.begin() + u);
|
||||
VertexDescriptor numV = num_vertices(g);
|
||||
VertexDescriptor v;
|
||||
if (u != numV) {
|
||||
for (v = 0; v < numV; ++v) {
|
||||
reindexEdgeList(g.getOutEdgeList(v), u);
|
||||
}
|
||||
|
||||
for (v = 0; v < numV; ++v) {
|
||||
reindexEdgeList(g.getInEdgeList(v), u);
|
||||
}
|
||||
|
||||
auto ei = g.edges.begin();
|
||||
auto eiEnd = g.edges.end();
|
||||
for (; ei != eiEnd; ++ei) {
|
||||
if (ei->source > u) {
|
||||
--ei->source;
|
||||
}
|
||||
if (ei->target > u) {
|
||||
--ei->target;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class Graph>
|
||||
inline void removeVectorOwner(Graph &g, typename Graph::vertex_descriptor u) {
|
||||
// might make children detached
|
||||
g.mObjects.erase(g.mObjects.begin() + u);
|
||||
auto numV = num_vertices(g);
|
||||
if (u != numV) {
|
||||
for (typename Graph::vertex_descriptor v = 0; v < numV; ++v) {
|
||||
reindexEdgeList(g.getChildrenList(v), u);
|
||||
}
|
||||
|
||||
for (typename Graph::vertex_descriptor v = 0; v < numV; ++v) {
|
||||
reindexEdgeList(g.getParentsList(v), u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AddressableGraph
|
||||
template <class AddressableGraph>
|
||||
inline std::ptrdiff_t pathLength(typename AddressableGraph::vertex_descriptor u, const AddressableGraph &g,
|
||||
typename AddressableGraph::vertex_descriptor parentID = AddressableGraph::null_vertex()) noexcept {
|
||||
if (u == parentID) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const auto &pmap = get(boost::vertex_name, g);
|
||||
|
||||
std::ptrdiff_t sz = 0;
|
||||
while (u != parentID) {
|
||||
sz += static_cast<std::ptrdiff_t>(get(pmap, u).size()) + 1;
|
||||
u = parent(u, g);
|
||||
}
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
template <class AddressableGraph, class CharT, class Allocator>
|
||||
inline void pathComposite(
|
||||
std::basic_string<CharT, std::char_traits<CharT>, Allocator> &str,
|
||||
std::ptrdiff_t &sz,
|
||||
typename AddressableGraph::vertex_descriptor u, const AddressableGraph &g,
|
||||
typename AddressableGraph::vertex_descriptor parentID = AddressableGraph::null_vertex()) noexcept {
|
||||
const auto &pmap = get(boost::vertex_name, g);
|
||||
|
||||
while (u != parentID) {
|
||||
CC_EXPECTS(sz <= static_cast<std::ptrdiff_t>(str.size()));
|
||||
|
||||
const auto &name = get(pmap, u);
|
||||
sz -= static_cast<std::ptrdiff_t>(name.size()) + 1;
|
||||
CC_ENSURES(sz >= 0);
|
||||
str[sz] = '/';
|
||||
std::copy(name.begin(), name.end(), str.begin() + sz + 1);
|
||||
|
||||
u = parent(u, g);
|
||||
}
|
||||
CC_ENSURES(sz == 0);
|
||||
}
|
||||
|
||||
template <class Key>
|
||||
struct ColorMap : public boost::put_get_helper<boost::default_color_type &, ColorMap<Key>> {
|
||||
using value_type = boost::default_color_type;
|
||||
using reference = boost::default_color_type &;
|
||||
using key_type = Key;
|
||||
using category = boost::lvalue_property_map_tag;
|
||||
|
||||
ColorMap(ccstd::pmr::vector<boost::default_color_type> &vec) noexcept // NOLINT(google-explicit-constructor)
|
||||
: container{&vec} {}
|
||||
|
||||
inline reference operator[](const key_type &v) const noexcept {
|
||||
return (*container)[v];
|
||||
}
|
||||
inline reference operator()(const key_type &v) const noexcept {
|
||||
return operator[](v);
|
||||
}
|
||||
|
||||
ccstd::pmr::vector<boost::default_color_type> *container{};
|
||||
};
|
||||
|
||||
} // namespace impl
|
||||
|
||||
} // namespace render
|
||||
|
||||
} // namespace cc
|
||||
|
||||
namespace std {
|
||||
|
||||
template <class DirectedCategory, class VertexDescriptor>
|
||||
struct hash<cc::render::impl::EdgeDescriptor<DirectedCategory, VertexDescriptor>> {
|
||||
size_t operator()(const cc::render::impl::EdgeDescriptor<DirectedCategory, VertexDescriptor> &e) const noexcept {
|
||||
return boost::hash_value(e.get_property());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
627
cocos/renderer/pipeline/custom/details/GraphTypes.h
Normal file
627
cocos/renderer/pipeline/custom/details/GraphTypes.h
Normal file
@@ -0,0 +1,627 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/container/pmr/polymorphic_allocator.hpp>
|
||||
#include <boost/iterator/iterator_adaptor.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include "cocos/base/memory/Memory.h"
|
||||
#include "cocos/base/std/container/list.h"
|
||||
#include "cocos/base/std/container/string.h"
|
||||
#include "cocos/base/std/variant.h"
|
||||
#include "cocos/renderer/pipeline/custom/details/Overload.h"
|
||||
|
||||
namespace boost {
|
||||
|
||||
struct use_default;
|
||||
|
||||
struct directed_tag;
|
||||
struct undirected_tag;
|
||||
struct bidirectional_tag;
|
||||
|
||||
struct no_property;
|
||||
|
||||
} // namespace boost
|
||||
|
||||
namespace cc {
|
||||
|
||||
template <class T>
|
||||
using PmrList = ccstd::list<T, boost::container::pmr::polymorphic_allocator<T>>;
|
||||
|
||||
namespace render {
|
||||
|
||||
template <class... Ts>
|
||||
struct VertexOverloaded : Overloaded<Ts...> {
|
||||
VertexOverloaded(Ts &&...ts) // NOLINT
|
||||
: Overloaded<Ts...>{std::forward<Ts>(ts)...} {}
|
||||
template <class T>
|
||||
auto operator()(T *ptr) {
|
||||
return this->Overloaded<Ts...>::operator()(*ptr);
|
||||
}
|
||||
};
|
||||
|
||||
template <class GraphT, class... Ts>
|
||||
auto visitObject(typename GraphT::vertex_descriptor v, GraphT &g, Ts &&...args) {
|
||||
return ccstd::visit(VertexOverloaded<Ts...>{std::forward<Ts>(args)...}, value(v, g));
|
||||
}
|
||||
|
||||
namespace impl {
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// EdgeDescriptor
|
||||
//--------------------------------------------------------------------
|
||||
template <class DirectedCategory, class VertexDescriptor>
|
||||
struct EdgeDescriptor {
|
||||
EdgeDescriptor() = default;
|
||||
EdgeDescriptor(VertexDescriptor s, VertexDescriptor t) noexcept // NOLINT
|
||||
: source(s), target(t) {}
|
||||
|
||||
void expectsNoProperty() const noexcept {
|
||||
// CC_EXPECTS(false);
|
||||
}
|
||||
VertexDescriptor source{static_cast<VertexDescriptor>(-1)};
|
||||
VertexDescriptor target{static_cast<VertexDescriptor>(-1)};
|
||||
};
|
||||
|
||||
template <class VertexDescriptor>
|
||||
inline bool operator==(
|
||||
const EdgeDescriptor<boost::directed_tag, VertexDescriptor> &lhs,
|
||||
const EdgeDescriptor<boost::directed_tag, VertexDescriptor> &rhs) noexcept {
|
||||
return lhs.source == rhs.source &&
|
||||
lhs.target == rhs.target;
|
||||
}
|
||||
|
||||
template <class VertexDescriptor>
|
||||
inline bool operator==(
|
||||
const EdgeDescriptor<boost::bidirectional_tag, VertexDescriptor> &lhs,
|
||||
const EdgeDescriptor<boost::bidirectional_tag, VertexDescriptor> &rhs) noexcept {
|
||||
return lhs.source == rhs.source &&
|
||||
lhs.target == rhs.target;
|
||||
}
|
||||
|
||||
template <class VertexDescriptor>
|
||||
inline bool operator!=(
|
||||
const EdgeDescriptor<boost::directed_tag, VertexDescriptor> &lhs,
|
||||
const EdgeDescriptor<boost::directed_tag, VertexDescriptor> &rhs) noexcept {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template <class VertexDescriptor>
|
||||
inline bool operator!=(
|
||||
const EdgeDescriptor<boost::bidirectional_tag, VertexDescriptor> &lhs,
|
||||
const EdgeDescriptor<boost::bidirectional_tag, VertexDescriptor> &rhs) noexcept {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template <class DirectedCategory, class VertexDescriptor>
|
||||
struct EdgeDescriptorWithProperty : EdgeDescriptor<DirectedCategory, VertexDescriptor> {
|
||||
using property_type = void;
|
||||
|
||||
EdgeDescriptorWithProperty() = default;
|
||||
EdgeDescriptorWithProperty(VertexDescriptor s, VertexDescriptor t, const property_type *p) noexcept
|
||||
: EdgeDescriptor<DirectedCategory, VertexDescriptor>(s, t), edgeProperty(const_cast<property_type *>(p)) {}
|
||||
|
||||
property_type *get_property() const noexcept { // NOLINT
|
||||
return edgeProperty;
|
||||
}
|
||||
|
||||
property_type *edgeProperty{};
|
||||
};
|
||||
|
||||
template <class DirectedCategory, class VertexDescriptor>
|
||||
inline bool operator==(
|
||||
const EdgeDescriptorWithProperty<DirectedCategory, VertexDescriptor> &lhs,
|
||||
const EdgeDescriptorWithProperty<DirectedCategory, VertexDescriptor> &rhs) noexcept {
|
||||
return lhs.edgeProperty == rhs.edgeProperty;
|
||||
}
|
||||
|
||||
template <class DirectedCategory, class VertexDescriptor>
|
||||
inline bool operator!=(
|
||||
const EdgeDescriptorWithProperty<DirectedCategory, VertexDescriptor> &lhs,
|
||||
const EdgeDescriptorWithProperty<DirectedCategory, VertexDescriptor> &rhs) noexcept {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template <class DirectedCategory, class VertexDescriptor>
|
||||
inline bool operator<(
|
||||
const EdgeDescriptorWithProperty<DirectedCategory, VertexDescriptor> &lhs,
|
||||
const EdgeDescriptorWithProperty<DirectedCategory, VertexDescriptor> &rhs) noexcept {
|
||||
return lhs.edgeProperty < rhs.edgeProperty;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// StoredEdge
|
||||
//--------------------------------------------------------------------
|
||||
template <class VertexDescriptor>
|
||||
class StoredEdge {
|
||||
public:
|
||||
StoredEdge(VertexDescriptor target) noexcept // NOLINT(google-explicit-constructor)
|
||||
: target(target) {}
|
||||
const VertexDescriptor &get_target() const noexcept { // NOLINT
|
||||
return target;
|
||||
}
|
||||
VertexDescriptor &get_target() noexcept { // NOLINT
|
||||
return target;
|
||||
}
|
||||
// auto operator<=>(const StoredEdge&) const noexcept = default;
|
||||
|
||||
VertexDescriptor target;
|
||||
};
|
||||
|
||||
template <class VertexDescriptor>
|
||||
inline bool operator==(
|
||||
const StoredEdge<VertexDescriptor> &lhs,
|
||||
const StoredEdge<VertexDescriptor> &rhs) noexcept {
|
||||
return lhs.target == rhs.target;
|
||||
}
|
||||
|
||||
template <class VertexDescriptor>
|
||||
inline bool operator!=(
|
||||
const StoredEdge<VertexDescriptor> &lhs,
|
||||
const StoredEdge<VertexDescriptor> &rhs) noexcept {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template <class VertexDescriptor>
|
||||
inline bool operator<(
|
||||
const StoredEdge<VertexDescriptor> &lhs,
|
||||
const StoredEdge<VertexDescriptor> &rhs) noexcept {
|
||||
return lhs.target < rhs.target;
|
||||
}
|
||||
|
||||
template <class VertexDescriptor, class EdgeProperty>
|
||||
class StoredEdgeWithProperty : public StoredEdge<VertexDescriptor> {
|
||||
public:
|
||||
StoredEdgeWithProperty(VertexDescriptor target, const EdgeProperty &p)
|
||||
: StoredEdge<VertexDescriptor>(target), property(ccnew EdgeProperty(p)) {}
|
||||
StoredEdgeWithProperty(VertexDescriptor target, std::unique_ptr<EdgeProperty> &&ptr)
|
||||
: StoredEdge<VertexDescriptor>(target), property(std::move(ptr)) {}
|
||||
StoredEdgeWithProperty(VertexDescriptor target) // NOLINT(google-explicit-constructor)
|
||||
: StoredEdge<VertexDescriptor>(target) {}
|
||||
|
||||
StoredEdgeWithProperty(StoredEdgeWithProperty &&) noexcept = default;
|
||||
StoredEdgeWithProperty &operator=(StoredEdgeWithProperty &&) noexcept = default;
|
||||
|
||||
EdgeProperty &get_property() noexcept { // NOLINT
|
||||
CC_EXPECTS(property);
|
||||
return *property;
|
||||
}
|
||||
const EdgeProperty &get_property() const noexcept { // NOLINT
|
||||
CC_EXPECTS(property);
|
||||
return *property;
|
||||
}
|
||||
std::unique_ptr<EdgeProperty> property;
|
||||
};
|
||||
|
||||
template <class VertexDescriptor, class EdgeListIter, class EdgeProperty = boost::no_property>
|
||||
class StoredEdgeWithEdgeIter : public StoredEdge<VertexDescriptor> {
|
||||
public:
|
||||
StoredEdgeWithEdgeIter(VertexDescriptor v, EdgeListIter iter) noexcept
|
||||
: StoredEdge<VertexDescriptor>(v), _edgeListIter(iter) {}
|
||||
StoredEdgeWithEdgeIter(VertexDescriptor v) noexcept // NOLINT(google-explicit-constructor)
|
||||
: StoredEdge<VertexDescriptor>(v) {}
|
||||
|
||||
EdgeListIter get_iter() const noexcept { // NOLINT
|
||||
return _edgeListIter;
|
||||
}
|
||||
EdgeProperty &get_property() noexcept { // NOLINT
|
||||
return _edgeListIter->get_property();
|
||||
}
|
||||
const EdgeProperty &get_property() const noexcept { // NOLINT
|
||||
return _edgeListIter->get_property();
|
||||
}
|
||||
|
||||
protected:
|
||||
EdgeListIter _edgeListIter{};
|
||||
};
|
||||
|
||||
template <class VertexDescriptor, class EdgeVec, class EdgeProperty = boost::no_property>
|
||||
class StoredEdgeWithRandomAccessEdgeIter : public StoredEdge<VertexDescriptor> {
|
||||
public:
|
||||
StoredEdgeWithRandomAccessEdgeIter(
|
||||
VertexDescriptor v, typename EdgeVec::iterator i, EdgeVec *edgeVec) noexcept
|
||||
: StoredEdge<VertexDescriptor>(v), _id(i - edgeVec->begin()), _vector(edgeVec) {}
|
||||
|
||||
typename EdgeVec::iterator get_iter() const noexcept { // NOLINT
|
||||
CC_EXPECTS(_vector);
|
||||
return _vector->begin() + _id;
|
||||
}
|
||||
EdgeProperty &get_property() noexcept { // NOLINT
|
||||
CC_EXPECTS(_vector);
|
||||
return (*_vector)[_id].get_property();
|
||||
}
|
||||
const EdgeProperty &get_property() const noexcept { // NOLINT
|
||||
CC_EXPECTS(_vector);
|
||||
return (*_vector)[_id].get_property();
|
||||
}
|
||||
|
||||
protected:
|
||||
size_t _id{static_cast<size_t>(-1)};
|
||||
EdgeVec *_vector{};
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// VertexIterator
|
||||
//--------------------------------------------------------------------
|
||||
template <class BaseIter, class VertexDescriptor, class Difference>
|
||||
struct VertexIter : boost::iterator_adaptor<
|
||||
VertexIter<BaseIter, VertexDescriptor, Difference>,
|
||||
BaseIter, VertexDescriptor, boost::use_default, VertexDescriptor, Difference> {
|
||||
using Base = boost::iterator_adaptor<
|
||||
VertexIter<BaseIter, VertexDescriptor, Difference>,
|
||||
BaseIter, VertexDescriptor, boost::use_default, VertexDescriptor, Difference>;
|
||||
|
||||
VertexIter() = default;
|
||||
VertexIter(const BaseIter &i) noexcept // NOLINT(google-explicit-constructor)
|
||||
: Base(i) {}
|
||||
|
||||
VertexDescriptor dereference() const noexcept {
|
||||
return VertexDescriptor{&(*this->base())};
|
||||
}
|
||||
};
|
||||
|
||||
template <class BaseIter, class VertexDescriptor, class Difference>
|
||||
struct VertexMapPtrIter : boost::iterator_adaptor<
|
||||
VertexMapPtrIter<BaseIter, VertexDescriptor, Difference>,
|
||||
BaseIter, VertexDescriptor, boost::use_default, VertexDescriptor, Difference> {
|
||||
using Base = boost::iterator_adaptor<
|
||||
VertexMapPtrIter<BaseIter, VertexDescriptor, Difference>,
|
||||
BaseIter, VertexDescriptor, boost::use_default, VertexDescriptor, Difference>;
|
||||
|
||||
VertexMapPtrIter() = default;
|
||||
VertexMapPtrIter(const BaseIter &i) noexcept // NOLINT(google-explicit-constructor)
|
||||
: Base(i) {}
|
||||
|
||||
VertexDescriptor dereference() const noexcept {
|
||||
return VertexDescriptor{this->base()->second.get()};
|
||||
}
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// OutEdgeIterator
|
||||
//--------------------------------------------------------------------
|
||||
template <class BaseIter, class VertexDescriptor, class EdgeDescriptor, class Difference>
|
||||
struct OutEdgeIter : boost::iterator_adaptor<
|
||||
OutEdgeIter<BaseIter, VertexDescriptor, EdgeDescriptor, Difference>,
|
||||
BaseIter, EdgeDescriptor, boost::use_default, EdgeDescriptor, Difference> {
|
||||
using Base = boost::iterator_adaptor<
|
||||
OutEdgeIter<BaseIter, VertexDescriptor, EdgeDescriptor, Difference>,
|
||||
BaseIter, EdgeDescriptor, boost::use_default, EdgeDescriptor, Difference>;
|
||||
|
||||
OutEdgeIter() = default;
|
||||
OutEdgeIter(const BaseIter &i, const VertexDescriptor &src) noexcept
|
||||
: Base(i), source(src) {}
|
||||
|
||||
EdgeDescriptor dereference() const noexcept {
|
||||
// this->base() return out edge list iterator
|
||||
return EdgeDescriptor{
|
||||
source, (*this->base()).get_target()};
|
||||
}
|
||||
VertexDescriptor source{};
|
||||
};
|
||||
|
||||
template <class BaseIter, class VertexDescriptor, class EdgeDescriptor, class Difference>
|
||||
struct OutPropertyEdgeIter : boost::iterator_adaptor<
|
||||
OutPropertyEdgeIter<BaseIter, VertexDescriptor, EdgeDescriptor, Difference>,
|
||||
BaseIter, EdgeDescriptor, boost::use_default, EdgeDescriptor, Difference> {
|
||||
using Base = boost::iterator_adaptor<
|
||||
OutPropertyEdgeIter<BaseIter, VertexDescriptor, EdgeDescriptor, Difference>,
|
||||
BaseIter, EdgeDescriptor, boost::use_default, EdgeDescriptor, Difference>;
|
||||
|
||||
OutPropertyEdgeIter() = default;
|
||||
OutPropertyEdgeIter(const BaseIter &i, const VertexDescriptor &src) noexcept
|
||||
: Base(i), source(src) {}
|
||||
|
||||
EdgeDescriptor dereference() const noexcept {
|
||||
// this->base() return out edge list iterator
|
||||
return EdgeDescriptor{
|
||||
source, (*this->base()).get_target(), &(*this->base()).get_property()};
|
||||
}
|
||||
VertexDescriptor source{};
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// InEdgeIterator
|
||||
//--------------------------------------------------------------------
|
||||
template <class BaseIter, class VertexDescriptor, class EdgeDescriptor, class Difference>
|
||||
struct InEdgeIter : boost::iterator_adaptor<
|
||||
InEdgeIter<BaseIter, VertexDescriptor, EdgeDescriptor, Difference>,
|
||||
BaseIter, EdgeDescriptor, boost::use_default, EdgeDescriptor, Difference> {
|
||||
using Base = boost::iterator_adaptor<
|
||||
InEdgeIter<BaseIter, VertexDescriptor, EdgeDescriptor, Difference>,
|
||||
BaseIter, EdgeDescriptor, boost::use_default, EdgeDescriptor, Difference>;
|
||||
|
||||
InEdgeIter() = default;
|
||||
InEdgeIter(const BaseIter &i, const VertexDescriptor &src) noexcept
|
||||
: Base(i), source(src) {}
|
||||
|
||||
EdgeDescriptor dereference() const noexcept {
|
||||
return EdgeDescriptor{
|
||||
(*this->base()).get_target(), source};
|
||||
}
|
||||
VertexDescriptor source{};
|
||||
};
|
||||
|
||||
template <class BaseIter, class VertexDescriptor, class EdgeDescriptor, class Difference>
|
||||
struct InPropertyEdgeIter : boost::iterator_adaptor<
|
||||
InPropertyEdgeIter<BaseIter, VertexDescriptor, EdgeDescriptor, Difference>,
|
||||
BaseIter, EdgeDescriptor, boost::use_default, EdgeDescriptor, Difference> {
|
||||
using Base = boost::iterator_adaptor<
|
||||
InPropertyEdgeIter<BaseIter, VertexDescriptor, EdgeDescriptor, Difference>,
|
||||
BaseIter, EdgeDescriptor, boost::use_default, EdgeDescriptor, Difference>;
|
||||
|
||||
InPropertyEdgeIter() = default;
|
||||
InPropertyEdgeIter(const BaseIter &i, const VertexDescriptor &src) noexcept
|
||||
: Base(i), source(src) {}
|
||||
|
||||
EdgeDescriptor dereference() const noexcept {
|
||||
return EdgeDescriptor{
|
||||
(*this->base()).get_target(), source, &this->base()->get_property()};
|
||||
}
|
||||
VertexDescriptor source{};
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// EdgeIterator
|
||||
//--------------------------------------------------------------------
|
||||
// UndirectedEdgeIter (Bidirectional || Undirected)
|
||||
template <class EdgeIter, class EdgeDescriptor, class Difference>
|
||||
struct UndirectedEdgeIter : boost::iterator_adaptor<
|
||||
UndirectedEdgeIter<EdgeIter, EdgeDescriptor, Difference>,
|
||||
EdgeIter, EdgeDescriptor, boost::use_default, EdgeDescriptor, Difference> {
|
||||
using Base = boost::iterator_adaptor<
|
||||
UndirectedEdgeIter<EdgeIter, EdgeDescriptor, Difference>,
|
||||
EdgeIter, EdgeDescriptor, boost::use_default, EdgeDescriptor, Difference>;
|
||||
|
||||
UndirectedEdgeIter() = default;
|
||||
explicit UndirectedEdgeIter(EdgeIter i) noexcept : Base(i) {}
|
||||
|
||||
EdgeDescriptor dereference() const noexcept {
|
||||
return EdgeDescriptor{
|
||||
(*this->base()).source, (*this->base()).target, &this->base()->get_property()};
|
||||
}
|
||||
};
|
||||
|
||||
// DirectedEdgeIterator
|
||||
template <class VertexIterator, class OutEdgeIterator, class Graph>
|
||||
class DirectedEdgeIterator {
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using value_type = typename OutEdgeIterator::value_type;
|
||||
using reference = typename OutEdgeIterator::reference;
|
||||
using pointer = typename OutEdgeIterator::pointer;
|
||||
using difference_type = typename OutEdgeIterator::difference_type;
|
||||
using distance_type = difference_type;
|
||||
|
||||
DirectedEdgeIterator() = default;
|
||||
template <class G>
|
||||
DirectedEdgeIterator(VertexIterator b, VertexIterator c, VertexIterator e, const G &g) noexcept
|
||||
: _begin(b), _curr(c), _end(e), _g(&g) {
|
||||
if (_curr != _end) {
|
||||
while (_curr != _end && out_degree(*_curr, *_g) == 0) {
|
||||
++_curr;
|
||||
}
|
||||
if (_curr != _end) {
|
||||
_edges = out_edges(*_curr, *_g);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DirectedEdgeIterator &operator++() noexcept {
|
||||
++_edges->first;
|
||||
if (_edges->first == _edges->second) {
|
||||
++_curr;
|
||||
while (_curr != _end && out_degree(*_curr, *_g) == 0) {
|
||||
++_curr;
|
||||
}
|
||||
if (_curr != _end) {
|
||||
_edges = out_edges(*_curr, *_g);
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
DirectedEdgeIterator operator++(int) noexcept {
|
||||
DirectedEdgeIterator tmp = *this;
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
value_type operator*() const noexcept {
|
||||
return *_edges->first;
|
||||
}
|
||||
bool operator==(const DirectedEdgeIterator &x) const noexcept {
|
||||
return _curr == x._curr && (_curr == _end || _edges->first == x._edges->first);
|
||||
}
|
||||
bool operator!=(const DirectedEdgeIterator &x) const noexcept {
|
||||
return _curr != x._curr || (_curr != _end && _edges->first != x._edges->first);
|
||||
}
|
||||
|
||||
protected:
|
||||
VertexIterator _begin{};
|
||||
VertexIterator _curr{};
|
||||
VertexIterator _end{};
|
||||
boost::optional<std::pair<OutEdgeIterator, OutEdgeIterator>> _edges;
|
||||
const Graph *_g{};
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// EdgeListGraph
|
||||
//--------------------------------------------------------------------
|
||||
template <class VertexDescriptor, class EdgeProperty = boost::no_property>
|
||||
struct ListEdge {
|
||||
ListEdge(VertexDescriptor s, VertexDescriptor t) // NOLINT
|
||||
: source(s), target(t) {}
|
||||
|
||||
ListEdge(VertexDescriptor s, VertexDescriptor t, EdgeProperty &&p) // NOLINT
|
||||
: source(s), target(t), property(std::move(p)) {}
|
||||
|
||||
ListEdge(VertexDescriptor s, VertexDescriptor t, const EdgeProperty &p) // NOLINT
|
||||
: source(s), target(t), property(p) {}
|
||||
|
||||
template <class... T>
|
||||
ListEdge(VertexDescriptor s, VertexDescriptor t, T &&...args) // NOLINT
|
||||
: source(s), target(t), property(std::forward<T>(args)...) {}
|
||||
|
||||
EdgeProperty &get_property() noexcept { return property; } // NOLINT
|
||||
const EdgeProperty &get_property() const noexcept { return property; } // NOLINT
|
||||
|
||||
VertexDescriptor source{};
|
||||
VertexDescriptor target{};
|
||||
EdgeProperty property;
|
||||
};
|
||||
|
||||
// template<class VertexDescriptor, PmrAllocatorUserClass_ EdgeProperty>
|
||||
template <class VertexDescriptor, class EdgeProperty>
|
||||
struct PmrListEdge {
|
||||
using allocator_type = boost::container::pmr::polymorphic_allocator<char>;
|
||||
allocator_type get_allocator() const noexcept { // NOLINT
|
||||
return allocator_type{property.get_allocator().resource()};
|
||||
}
|
||||
// cntrs
|
||||
PmrListEdge(VertexDescriptor s, VertexDescriptor t, const allocator_type &alloc) // NOLINT
|
||||
: source(s), target(t), property(alloc) {}
|
||||
|
||||
PmrListEdge(VertexDescriptor s, VertexDescriptor t, EdgeProperty &&p, const allocator_type &alloc) // NOLINT
|
||||
: source(s), target(t), property(std::move(p), alloc) {}
|
||||
|
||||
PmrListEdge(VertexDescriptor s, VertexDescriptor t, const EdgeProperty &p, const allocator_type &alloc) // NOLINT
|
||||
: source(s), target(t), property(p, alloc) {}
|
||||
|
||||
template <class... T>
|
||||
PmrListEdge(VertexDescriptor s, VertexDescriptor t, T &&...args) // NOLINT
|
||||
: source(s), target(t), property(std::forward<T>(args)...) {}
|
||||
|
||||
// move/copy cntrs
|
||||
PmrListEdge(PmrListEdge &&rhs, const allocator_type &alloc)
|
||||
: source(std::move(rhs.source)), target(std::move(rhs.target)), property(std::move(rhs.property), alloc) {}
|
||||
PmrListEdge(const PmrListEdge &rhs, const allocator_type &alloc)
|
||||
: source(rhs.source), target(rhs.target), property(rhs.property, alloc) {}
|
||||
|
||||
PmrListEdge(const PmrListEdge &) = delete;
|
||||
|
||||
EdgeProperty &get_property() noexcept { return property; } // NOLINT
|
||||
const EdgeProperty &get_property() const noexcept { return property; } // NOLINT
|
||||
|
||||
VertexDescriptor source{};
|
||||
VertexDescriptor target{};
|
||||
EdgeProperty property;
|
||||
};
|
||||
|
||||
// Polymorphic Graph
|
||||
template <class Tag, class Handle>
|
||||
struct ValueHandle : Tag {
|
||||
ValueHandle() noexcept = default;
|
||||
ValueHandle(ValueHandle &&rhs) noexcept
|
||||
: value(std::move(rhs.value)) {}
|
||||
ValueHandle(const ValueHandle &rhs) noexcept
|
||||
: value(rhs.value) {}
|
||||
ValueHandle &operator=(ValueHandle &&rhs) noexcept {
|
||||
value = std::move(rhs.value);
|
||||
return *this;
|
||||
}
|
||||
ValueHandle &operator=(const ValueHandle &rhs) noexcept {
|
||||
value = rhs.value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ValueHandle(const Handle &handle) noexcept // NOLINT(google-explicit-constructor)
|
||||
: value(handle) {}
|
||||
ValueHandle(Handle &&handle) noexcept // NOLINT(google-explicit-constructor)
|
||||
: value(std::move(handle)) {}
|
||||
template <class... Args>
|
||||
ValueHandle(Args &&...args) noexcept // NOLINT(google-explicit-constructor)
|
||||
: value(std::forward<Args>(args)...) {}
|
||||
|
||||
Handle value{};
|
||||
};
|
||||
|
||||
// Reference Graph
|
||||
// OwnershipIterator (Bidirectional, !EdgeProperty)
|
||||
template <class VertexIterator, class OutEdgeIterator, class Graph>
|
||||
class OwnershipIterator {
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using value_type = typename OutEdgeIterator::value_type;
|
||||
using reference = typename OutEdgeIterator::reference;
|
||||
using pointer = typename OutEdgeIterator::pointer;
|
||||
using difference_type = typename OutEdgeIterator::difference_type;
|
||||
using distance_type = difference_type;
|
||||
|
||||
OwnershipIterator() = default;
|
||||
template <class G>
|
||||
OwnershipIterator(VertexIterator b, VertexIterator c, VertexIterator e, const G &g) noexcept
|
||||
: _begin(b), _curr(c), _end(e), _g(&g) {
|
||||
if (_curr != _end) {
|
||||
while (_curr != _end && numChildren(*_curr, *_g) == 0) {
|
||||
++_curr;
|
||||
}
|
||||
if (_curr != _end) {
|
||||
_edges = children(*_curr, *_g);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OwnershipIterator &operator++() noexcept {
|
||||
++_edges->first;
|
||||
if (_edges->first == _edges->second) {
|
||||
++_curr;
|
||||
while (_curr != _end && numChildren(*_curr, *_g) == 0) {
|
||||
++_curr;
|
||||
}
|
||||
if (_curr != _end) {
|
||||
_edges = children(*_curr, *_g);
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
OwnershipIterator operator++(int) noexcept {
|
||||
OwnershipIterator tmp = *this;
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
value_type operator*() const noexcept {
|
||||
return *_edges->first;
|
||||
}
|
||||
bool operator==(const OwnershipIterator &x) const noexcept {
|
||||
return _curr == x._curr && (_curr == _end || _edges->first == x._edges->first);
|
||||
}
|
||||
bool operator!=(const OwnershipIterator &x) const noexcept {
|
||||
return _curr != x._curr || (_curr != _end && _edges->first != x._edges->first);
|
||||
}
|
||||
|
||||
protected:
|
||||
VertexIterator _begin{};
|
||||
VertexIterator _curr{};
|
||||
VertexIterator _end{};
|
||||
boost::optional<std::pair<OutEdgeIterator, OutEdgeIterator>> _edges;
|
||||
const Graph *_g{};
|
||||
};
|
||||
|
||||
} // namespace impl
|
||||
|
||||
} // namespace render
|
||||
|
||||
} // namespace cc
|
||||
235
cocos/renderer/pipeline/custom/details/GraphView.h
Normal file
235
cocos/renderer/pipeline/custom/details/GraphView.h
Normal file
@@ -0,0 +1,235 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <boost/graph/adjacency_iterator.hpp>
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/properties.hpp>
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace render {
|
||||
|
||||
template <class GraphT>
|
||||
struct AddressableView {
|
||||
explicit AddressableView(const GraphT& g) noexcept
|
||||
: mGraph(g) {}
|
||||
|
||||
// GraphT
|
||||
using directed_category = boost::bidirectional_tag;
|
||||
using vertex_descriptor = typename GraphT::vertex_descriptor;
|
||||
using edge_descriptor = typename GraphT::ownership_descriptor;
|
||||
using edge_parallel_category = boost::allow_parallel_edge_tag;
|
||||
struct traversal_category // NOLINT(readability-identifier-naming)
|
||||
: virtual boost::incidence_graph_tag,
|
||||
virtual boost::bidirectional_graph_tag,
|
||||
virtual boost::adjacency_graph_tag,
|
||||
virtual boost::vertex_list_graph_tag,
|
||||
virtual boost::edge_list_graph_tag {};
|
||||
|
||||
static vertex_descriptor null_vertex() noexcept { // NOLINT(readability-identifier-naming)
|
||||
return GraphT::null_vertex();
|
||||
}
|
||||
|
||||
// IncidenceGraph
|
||||
using out_edge_iterator = typename GraphT::children_iterator;
|
||||
using degree_size_type = typename GraphT::children_size_type;
|
||||
|
||||
// BidirectionalGraph
|
||||
using in_edge_iterator = typename GraphT::parent_iterator;
|
||||
|
||||
// AdjacencyGraph
|
||||
using adjacency_iterator = typename boost::adjacency_iterator_generator<
|
||||
AddressableView, vertex_descriptor, out_edge_iterator>::type;
|
||||
|
||||
// VertexListGraph
|
||||
using vertex_iterator = typename GraphT::vertex_iterator;
|
||||
using vertices_size_type = typename GraphT::vertices_size_type;
|
||||
|
||||
// EdgeListGraph
|
||||
using edge_iterator = typename GraphT::ownership_iterator;
|
||||
using edges_size_type = typename GraphT::ownerships_size_type;
|
||||
|
||||
// Member
|
||||
const GraphT& mGraph;
|
||||
};
|
||||
|
||||
// IncidenceGraph
|
||||
template <class GraphT>
|
||||
inline typename AddressableView<GraphT>::vertex_descriptor
|
||||
source(const typename AddressableView<GraphT>::edge_descriptor& e, const AddressableView<GraphT>& g) noexcept {
|
||||
return parent(e, g.mGraph);
|
||||
}
|
||||
|
||||
template <class GraphT>
|
||||
inline typename AddressableView<GraphT>::vertex_descriptor
|
||||
target(const typename AddressableView<GraphT>::edge_descriptor& e, const AddressableView<GraphT>& g) noexcept {
|
||||
return child(e, g.mGraph);
|
||||
}
|
||||
|
||||
template <class GraphT>
|
||||
inline std::pair<
|
||||
typename AddressableView<GraphT>::out_edge_iterator,
|
||||
typename AddressableView<GraphT>::out_edge_iterator>
|
||||
out_edges( // NOLINT(readability-identifier-naming)
|
||||
typename AddressableView<GraphT>::vertex_descriptor u,
|
||||
const AddressableView<GraphT>& g) {
|
||||
return children(u, g.mGraph);
|
||||
}
|
||||
|
||||
template <class GraphT>
|
||||
inline typename AddressableView<GraphT>::degree_size_type
|
||||
out_degree( // NOLINT(readability-identifier-naming)
|
||||
typename AddressableView<GraphT>::vertex_descriptor u,
|
||||
const AddressableView<GraphT>& g) noexcept {
|
||||
return numChildren(u, g.mGraph);
|
||||
}
|
||||
|
||||
template <class GraphT>
|
||||
inline std::pair<typename AddressableView<GraphT>::edge_descriptor, bool>
|
||||
edge(typename AddressableView<GraphT>::vertex_descriptor u,
|
||||
typename AddressableView<GraphT>::vertex_descriptor v,
|
||||
const AddressableView<GraphT>& g) noexcept {
|
||||
return ownership(u, v, g.mGraph);
|
||||
}
|
||||
|
||||
// BidirectionalGraph
|
||||
template <class GraphT>
|
||||
inline std::pair<typename AddressableView<GraphT>::in_edge_iterator, typename AddressableView<GraphT>::in_edge_iterator>
|
||||
in_edges( // NOLINT(readability-identifier-naming)
|
||||
typename AddressableView<GraphT>::vertex_descriptor u,
|
||||
const AddressableView<GraphT>& g) noexcept {
|
||||
return parents(u, g.mGraph);
|
||||
}
|
||||
|
||||
template <class GraphT>
|
||||
inline typename AddressableView<GraphT>::degree_size_type
|
||||
in_degree( // NOLINT(readability-identifier-naming)
|
||||
typename AddressableView<GraphT>::vertex_descriptor u,
|
||||
const AddressableView<GraphT>& g) noexcept {
|
||||
return numParents(u, g.mGraph);
|
||||
}
|
||||
|
||||
template <class GraphT>
|
||||
inline typename AddressableView<GraphT>::degree_size_type
|
||||
degree(typename AddressableView<GraphT>::vertex_descriptor u, const AddressableView<GraphT>& g) noexcept {
|
||||
return out_degree(u, g) + in_degree(u, g);
|
||||
}
|
||||
|
||||
// AdjacencyGraph
|
||||
template <class GraphT>
|
||||
inline std::pair<
|
||||
typename AddressableView<GraphT>::adjacency_iterator,
|
||||
typename AddressableView<GraphT>::adjacency_iterator>
|
||||
adjacent_vertices( // NOLINT(readability-identifier-naming)
|
||||
typename AddressableView<GraphT>::vertex_descriptor u,
|
||||
const AddressableView<GraphT>& g) noexcept {
|
||||
auto r = out_edges(u, g);
|
||||
return std::make_pair(
|
||||
typename AddressableView<GraphT>::adjacency_iterator(r.first, &g),
|
||||
typename AddressableView<GraphT>::adjacency_iterator(r.second, &g));
|
||||
}
|
||||
|
||||
// VertexListGraph
|
||||
template <class GraphT>
|
||||
inline std::pair<
|
||||
typename AddressableView<GraphT>::vertex_iterator,
|
||||
typename AddressableView<GraphT>::vertex_iterator>
|
||||
vertices(const AddressableView<GraphT>& g) noexcept {
|
||||
return vertices(g.mGraph);
|
||||
}
|
||||
|
||||
template <class GraphT>
|
||||
inline typename AddressableView<GraphT>::vertices_size_type
|
||||
num_vertices(const AddressableView<GraphT>& g) noexcept { // NOLINT(readability-identifier-naming)
|
||||
return num_vertices(g.mGraph);
|
||||
}
|
||||
|
||||
// EdgeListGraph
|
||||
template <class GraphT>
|
||||
inline std::pair<
|
||||
typename AddressableView<GraphT>::edge_iterator,
|
||||
typename AddressableView<GraphT>::edge_iterator>
|
||||
edges(const AddressableView<GraphT>& g) noexcept {
|
||||
return ownerships(g.mGraph);
|
||||
}
|
||||
|
||||
template <class GraphT>
|
||||
inline typename AddressableView<GraphT>::edges_size_type
|
||||
num_edges(const AddressableView<GraphT>& g) noexcept { // NOLINT(readability-identifier-naming)
|
||||
return num_ownerships(g.mGraph);
|
||||
}
|
||||
|
||||
} // namespace render
|
||||
|
||||
} // namespace cc
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class GraphT, class TagT>
|
||||
struct property_map<cc::render::AddressableView<GraphT>, TagT> {
|
||||
using const_type = typename property_map<GraphT, TagT>::const_type;
|
||||
using type = typename property_map<GraphT, TagT>::type;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace render {
|
||||
|
||||
template <class TagT, class GraphT>
|
||||
typename boost::property_map<AddressableView<GraphT>, TagT>::const_type
|
||||
get(TagT t, const AddressableView<GraphT>& g) {
|
||||
return get(t, g.mGraph);
|
||||
}
|
||||
|
||||
template <class TagT, class GraphT>
|
||||
typename boost::property_map<AddressableView<GraphT>, TagT>::type
|
||||
get(TagT t, AddressableView<GraphT>& g) {
|
||||
return get(t, g.mGraph);
|
||||
}
|
||||
|
||||
template <class TagT, class GraphT>
|
||||
[[nodiscard]] inline decltype(auto)
|
||||
get(TagT tag, const AddressableView<GraphT>& g, typename AddressableView<GraphT>::vertex_descriptor v) noexcept {
|
||||
return get(get(tag, g), v);
|
||||
}
|
||||
|
||||
template <class TagT, class GraphT>
|
||||
[[nodiscard]] inline decltype(auto)
|
||||
get(TagT tag, AddressableView<GraphT>& g, typename AddressableView<GraphT>::vertex_descriptor v) noexcept {
|
||||
return get(get(tag, g), v);
|
||||
}
|
||||
|
||||
template <class TagT, class GraphT, class... Args>
|
||||
inline void put(TagT tag, AddressableView<GraphT>& g,
|
||||
typename AddressableView<GraphT>::vertex_descriptor v,
|
||||
Args&&... args) {
|
||||
put(get(tag, g), v, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
} // namespace render
|
||||
|
||||
} // namespace cc
|
||||
45
cocos/renderer/pipeline/custom/details/GslUtils.h
Normal file
45
cocos/renderer/pipeline/custom/details/GslUtils.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <utility>
|
||||
#include "cocos/base/Macros.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace gsl {
|
||||
|
||||
// narrow_cast(): a searchable way to do narrowing casts of values
|
||||
template <class T, class U>
|
||||
constexpr T narrow_cast(U &&u) noexcept { // NOLINT
|
||||
return static_cast<T>(std::forward<U>(u));
|
||||
}
|
||||
|
||||
#define CC_EXPECTS(cond) CC_ASSERT(cond) // NOLINT
|
||||
|
||||
#define CC_ENSURES(cond) CC_ASSERT(cond) // NOLINT
|
||||
|
||||
} // namespace gsl
|
||||
|
||||
} // namespace cc
|
||||
130
cocos/renderer/pipeline/custom/details/JsbConversion.h
Normal file
130
cocos/renderer/pipeline/custom/details/JsbConversion.h
Normal file
@@ -0,0 +1,130 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include "cocos/base/std/container/map.h"
|
||||
#include "cocos/base/std/container/string.h"
|
||||
#include "cocos/base/std/container/vector.h"
|
||||
#include "cocos/bindings/manual/jsb_conversions.h"
|
||||
#include "cocos/renderer/pipeline/custom/details/Map.h"
|
||||
|
||||
template <typename T, typename allocator>
|
||||
inline bool nativevalue_to_se( // NOLINT(readability-identifier-naming)
|
||||
const ccstd::vector<T, allocator> &from,
|
||||
se::Value &to, se::Object *ctx) {
|
||||
se::Object *array = se::Object::createArrayObject(from.size());
|
||||
se::Value tmp;
|
||||
for (size_t i = 0; i < from.size(); i++) {
|
||||
nativevalue_to_se(from[i], tmp, ctx);
|
||||
array->setArrayElement(static_cast<uint32_t>(i), tmp);
|
||||
}
|
||||
to.setObject(array);
|
||||
array->decRef();
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Value, typename Less, typename Allocator>
|
||||
inline bool nativevalue_to_se( // NOLINT(readability-identifier-naming)
|
||||
const ccstd::map<ccstd::string, Value, Less, Allocator> &from,
|
||||
se::Value &to, se::Object *ctx) {
|
||||
se::Object *ret = se::Object::createPlainObject();
|
||||
se::Value value;
|
||||
bool ok = true;
|
||||
for (auto &it : from) {
|
||||
ok &= nativevalue_to_se(it.second, value, ctx);
|
||||
cc_tmp_set_property(ret, it.first, value);
|
||||
}
|
||||
to.setObject(ret);
|
||||
ret->decRef();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool nativevalue_to_se( // NOLINT(readability-identifier-naming)
|
||||
const ccstd::pmr::string &from, se::Value &to, se::Object * /*ctx*/) {
|
||||
to.setString(from.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T, typename allocator>
|
||||
bool sevalue_to_native(const se::Value &from, ccstd::vector<T, allocator> *to, se::Object *ctx) { // NOLINT(readability-identifier-naming)
|
||||
if (from.isNullOrUndefined()) {
|
||||
to->clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
CC_ASSERT(from.toObject());
|
||||
se::Object *array = from.toObject();
|
||||
|
||||
if (array->isArray()) {
|
||||
uint32_t len = 0;
|
||||
array->getArrayLength(&len);
|
||||
to->resize(len);
|
||||
se::Value tmp;
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
array->getArrayElement(i, &tmp);
|
||||
if (!sevalue_to_native(tmp, to->data() + i, ctx)) {
|
||||
SE_LOGE("vector %s convert error at %d\n", typeid(T).name(), i);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (array->isTypedArray()) {
|
||||
CC_ASSERT(std::is_arithmetic<T>::value);
|
||||
uint8_t *data = nullptr;
|
||||
size_t dataLen = 0;
|
||||
array->getTypedArrayData(&data, &dataLen);
|
||||
to->assign(reinterpret_cast<T *>(data), reinterpret_cast<T *>(data + dataLen));
|
||||
return true;
|
||||
}
|
||||
|
||||
SE_LOGE("[warn] failed to convert to ccstd::vector\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Value, typename Less, typename Allocator>
|
||||
bool sevalue_to_native(const se::Value &from, ccstd::map<ccstd::string, Value, Less, Allocator> *to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
|
||||
se::Object *jsmap = from.toObject();
|
||||
ccstd::vector<ccstd::string> allKeys;
|
||||
jsmap->getAllKeys(&allKeys);
|
||||
bool ret = true;
|
||||
se::Value property;
|
||||
for (auto &it : allKeys) {
|
||||
if (jsmap->getProperty(it.c_str(), &property)) {
|
||||
auto &output = (*to)[it];
|
||||
ret &= sevalue_to_native(property, &output, jsmap);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool sevalue_to_native(const se::Value &from, ccstd::pmr::string *to, se::Object * /*ctx*/) { // NOLINT(readability-identifier-naming)
|
||||
if (!from.isNullOrUndefined()) {
|
||||
const auto &str = from.toString();
|
||||
to->assign(str.begin(), str.end());
|
||||
} else {
|
||||
to->clear();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
164
cocos/renderer/pipeline/custom/details/Map.h
Normal file
164
cocos/renderer/pipeline/custom/details/Map.h
Normal file
@@ -0,0 +1,164 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <boost/container/flat_map.hpp>
|
||||
#include <boost/container/pmr/flat_map.hpp>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include "cocos/base/std/container/unordered_map.h"
|
||||
#include "cocos/renderer/pipeline/custom/details/Pmr.h"
|
||||
#include "cocos/renderer/pipeline/custom/details/Utility.h"
|
||||
|
||||
// for std::less<> the transparent comparator
|
||||
// see https://stackoverflow.com/questions/20317413/what-are-transparent-comparators
|
||||
|
||||
namespace cc {
|
||||
|
||||
// map
|
||||
template <class Key, class Value>
|
||||
using PmrMap = std::map<
|
||||
Key, Value, std::less<Key>,
|
||||
boost::container::pmr::polymorphic_allocator<std::pair<const Key, Value>>>;
|
||||
|
||||
template <class Key, class Value>
|
||||
using PmrMultiMap = std::multimap<
|
||||
Key, Value, std::less<Key>,
|
||||
boost::container::pmr::polymorphic_allocator<std::pair<const Key, Value>>>;
|
||||
|
||||
template <class Key, class Value>
|
||||
using TransparentMap = std::map<Key, Value, std::less<>>;
|
||||
|
||||
template <class Key, class Value>
|
||||
using TransparentMultiMap = std::multimap<Key, Value, std::less<>>;
|
||||
|
||||
template <class Key, class Value>
|
||||
using PmrTransparentMap = std::map<
|
||||
Key, Value, std::less<>,
|
||||
boost::container::pmr::polymorphic_allocator<std::pair<const Key, Value>>>;
|
||||
|
||||
template <class Key, class Value>
|
||||
using PmrTransparentMultiMap = std::multimap<
|
||||
Key, Value, std::less<>,
|
||||
boost::container::pmr::polymorphic_allocator<std::pair<const Key, Value>>>;
|
||||
|
||||
// flat_map
|
||||
template <class Key, class Value>
|
||||
using FlatMap = boost::container::flat_map<Key, Value, std::less<>>;
|
||||
|
||||
template <class Key, class Value>
|
||||
using FlatMultiMap = boost::container::flat_multimap<Key, Value, std::less<>>;
|
||||
|
||||
template <class Key, class Value>
|
||||
using PmrFlatMap = boost::container::pmr::flat_map<Key, Value, std::less<>>;
|
||||
|
||||
template <class Key, class Value>
|
||||
using PmrFlatMultiMap = boost::container::pmr::flat_multimap<Key, Value, std::less<>>;
|
||||
|
||||
// unordered_map
|
||||
template <class Key, class Value>
|
||||
using PmrUnorderedMap = ccstd::pmr::unordered_map<Key, Value>;
|
||||
|
||||
template <class Key, class Value>
|
||||
using PmrUnorderedMultiMap = ccstd::pmr::unordered_multimap<Key, Value>;
|
||||
|
||||
// transparent string unordered_map
|
||||
template <class Key, class Value>
|
||||
using UnorderedStringMap = std::unordered_map<
|
||||
Key, Value,
|
||||
TransparentStringHash<typename Key::value_type>, std::equal_to<>>;
|
||||
|
||||
template <class Key, class Value>
|
||||
using UnorderedStringMultiMap = std::unordered_multimap<
|
||||
Key, Value,
|
||||
TransparentStringHash<typename Key::value_type>, std::equal_to<>>;
|
||||
|
||||
template <class Key, class Value>
|
||||
using PmrUnorderedStringMap = std::unordered_map<
|
||||
Key, Value,
|
||||
TransparentStringHash<typename Key::value_type>, std::equal_to<>,
|
||||
boost::container::pmr::polymorphic_allocator<std::pair<const Key, Value>>>;
|
||||
|
||||
template <class Key, class Value>
|
||||
using PmrUnorderedStringMultiMap = std::unordered_multimap<
|
||||
Key, Value,
|
||||
TransparentStringHash<typename Key::value_type>, std::equal_to<>,
|
||||
boost::container::pmr::polymorphic_allocator<std::pair<const Key, Value>>>;
|
||||
|
||||
template <class Key, class Value, class Allocator, class KeyLike>
|
||||
inline typename std::map<Key, Value, std::less<>, Allocator>::mapped_type&
|
||||
at(std::map<Key, Value, std::less<>, Allocator>& m, const KeyLike& key) {
|
||||
auto iter = m.find(key);
|
||||
if (iter == m.end()) {
|
||||
throw std::out_of_range("at(std::map) out of range");
|
||||
}
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
template <class Key, class Value, class Allocator, class KeyLike>
|
||||
inline typename std::map<Key, Value, std::less<>, Allocator>::mapped_type const&
|
||||
at(const std::map<Key, Value, std::less<>, Allocator>& m, const KeyLike& key) {
|
||||
auto iter = m.find(key);
|
||||
if (iter == m.end()) {
|
||||
throw std::out_of_range("at(std::map) out of range");
|
||||
}
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
template <class Key, class Value, class Allocator, class KeyLike>
|
||||
inline typename boost::container::flat_map<Key, Value, std::less<>, Allocator>::mapped_type&
|
||||
at(boost::container::flat_map<Key, Value, std::less<>, Allocator>& m, const KeyLike& key) {
|
||||
auto iter = m.find(key);
|
||||
if (iter == m.end()) {
|
||||
throw std::out_of_range("at(boost::container::flat_map) out of range");
|
||||
}
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
template <class Key, class Value, class Allocator, class KeyLike>
|
||||
inline typename boost::container::flat_map<Key, Value, std::less<>, Allocator>::mapped_type const&
|
||||
at(const boost::container::flat_map<Key, Value, std::less<>, Allocator>& m, const KeyLike& key) {
|
||||
auto iter = m.find(key);
|
||||
if (iter == m.end()) {
|
||||
throw std::out_of_range("at(boost::container::flat_map) out of range");
|
||||
}
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
|
||||
namespace ccstd {
|
||||
|
||||
template <class Key, class T, class Compare, class AllocatorOrContainer>
|
||||
struct hash<boost::container::flat_map<Key, T, Compare, AllocatorOrContainer>> {
|
||||
hash_t operator()(const boost::container::flat_map<Key, T, Compare, AllocatorOrContainer>& val) const noexcept {
|
||||
hash_t seed = 0;
|
||||
for (const auto& pair : val) {
|
||||
hash_combine(seed, pair);
|
||||
}
|
||||
return seed;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ccstd
|
||||
73
cocos/renderer/pipeline/custom/details/Overload.h
Normal file
73
cocos/renderer/pipeline/custom/details/Overload.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <boost/mp11/algorithm.hpp>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include "cocos/base/std/variant.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER <= 1920)
|
||||
// https://stackoverflow.com/questions/50510122/stdvariant-with-overloaded-lambdas-alternative-with-msvc
|
||||
template <class... Ts>
|
||||
struct Overloaded {}; // NOLINT
|
||||
|
||||
template <class T0>
|
||||
struct Overloaded<T0> : T0 {
|
||||
using T0::operator();
|
||||
Overloaded(T0 t0) // NOLINT
|
||||
: T0(std::move(t0)) {}
|
||||
};
|
||||
|
||||
template <class T0, class T1, class... Ts>
|
||||
struct Overloaded<T0, T1, Ts...> : T0, Overloaded<T1, Ts...> {
|
||||
using T0::operator();
|
||||
using Overloaded<T1, Ts...>::operator();
|
||||
Overloaded(T0 t0, T1 t1, Ts... ts)
|
||||
: T0(std::move(t0)), Overloaded<T1, Ts...>(std::move(t1), std::move(ts)...) {}
|
||||
};
|
||||
#else
|
||||
template <class... Ts>
|
||||
struct Overloaded : Ts... {
|
||||
using Ts::operator()...;
|
||||
};
|
||||
|
||||
template <class... Ts>
|
||||
Overloaded(Ts...) -> Overloaded<Ts...>;
|
||||
#endif
|
||||
|
||||
template <class... Ts>
|
||||
Overloaded<Ts...> overload(Ts&&... ts) {
|
||||
return {std::forward<Ts>(ts)...};
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
auto variantFromIndex(size_t index) -> V { // NOLINT
|
||||
return boost::mp11::mp_with_index<boost::mp11::mp_size<V>>(index,
|
||||
[](auto i) { return V(ccstd::in_place_index<i>); });
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
82
cocos/renderer/pipeline/custom/details/PathUtils.h
Normal file
82
cocos/renderer/pipeline/custom/details/PathUtils.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <string_view>
|
||||
#include "cocos/base/std/container/array.h"
|
||||
#include "cocos/renderer/pipeline/custom/details/GslUtils.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace render {
|
||||
|
||||
namespace impl {
|
||||
|
||||
template <class CharT, class Allocator>
|
||||
inline void cleanPath(std::basic_string<CharT, std::char_traits<CharT>, Allocator> &str) noexcept {
|
||||
using string_t = std::basic_string<CharT, std::char_traits<CharT>, Allocator>;
|
||||
constexpr CharT slash[] = {'/', '\0'};
|
||||
constexpr CharT doubleSlash[] = {'/', '/', '\0'};
|
||||
|
||||
CC_EXPECTS(!str.empty());
|
||||
CC_EXPECTS(boost::algorithm::starts_with(str, std::string_view(slash)));
|
||||
CC_EXPECTS(str.find(doubleSlash) == string_t::npos);
|
||||
|
||||
{ // remove all /./
|
||||
constexpr CharT current[] = {'/', '.', '/', '\0'};
|
||||
|
||||
auto pos = str.rfind(current);
|
||||
while (pos != string_t::npos) {
|
||||
str.erase(pos, 2);
|
||||
pos = str.rfind(current);
|
||||
}
|
||||
// remove tailing /.
|
||||
constexpr CharT ending[] = {'/', '.', '\0'};
|
||||
if (boost::algorithm::ends_with(str, std::string_view(ending))) {
|
||||
str.resize(str.size() - 2);
|
||||
}
|
||||
}
|
||||
|
||||
// try remove /..
|
||||
constexpr ccstd::array<CharT, 4> previous = {CharT('/'), CharT('.'), CharT('.'), CharT('\0')};
|
||||
auto pos = str.find(previous.data());
|
||||
while (pos != string_t::npos) {
|
||||
if (pos == 0) {
|
||||
// root element has not parent path
|
||||
str = {}; // slash;
|
||||
return;
|
||||
}
|
||||
auto beg = str.rfind(slash, pos - 1);
|
||||
CC_EXPECTS(beg != string_t::npos);
|
||||
str.erase(beg, pos - beg + previous.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace impl
|
||||
|
||||
} // namespace render
|
||||
|
||||
} // namespace cc
|
||||
79
cocos/renderer/pipeline/custom/details/Pmr.h
Normal file
79
cocos/renderer/pipeline/custom/details/Pmr.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <boost/container/pmr/global_resource.hpp>
|
||||
#include <boost/container/pmr/polymorphic_allocator.hpp>
|
||||
#include <boost/container/pmr/unsynchronized_pool_resource.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace render {
|
||||
|
||||
template <class T>
|
||||
struct PmrDeallocator {
|
||||
void operator()(T* ptr) noexcept {
|
||||
mAllocator.deallocate(ptr, 1);
|
||||
}
|
||||
boost::container::pmr::polymorphic_allocator<T> mAllocator;
|
||||
};
|
||||
|
||||
template <class T, class... Args>
|
||||
[[nodiscard]] T*
|
||||
newPmr(boost::container::pmr::memory_resource* mr, Args&&... args) {
|
||||
boost::container::pmr::polymorphic_allocator<T> alloc(mr);
|
||||
|
||||
std::unique_ptr<T, PmrDeallocator<T>> ptr{
|
||||
alloc.allocate(1), PmrDeallocator<T>{alloc}};
|
||||
|
||||
// construct, might throw
|
||||
alloc.construct(ptr.get(), std::forward<Args>(args)...);
|
||||
|
||||
return ptr.release();
|
||||
}
|
||||
|
||||
struct PmrDeleter {
|
||||
template <class T>
|
||||
void operator()(T* ptr) const noexcept {
|
||||
if (ptr) {
|
||||
boost::container::pmr::polymorphic_allocator<T> alloc(ptr->get_allocator());
|
||||
ptr->~T();
|
||||
alloc.deallocate(ptr, 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
using PmrUniquePtr = std::unique_ptr<T, PmrDeleter>;
|
||||
|
||||
template <class T, class... Args>
|
||||
PmrUniquePtr<T>
|
||||
allocatePmrUniquePtr(const boost::container::pmr::polymorphic_allocator<std::byte>& alloc, Args&&... args) {
|
||||
return PmrUniquePtr<T>(newPmr<T>(alloc.resource(), std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
} // namespace render
|
||||
|
||||
} // namespace cc
|
||||
36
cocos/renderer/pipeline/custom/details/Range.h
Normal file
36
cocos/renderer/pipeline/custom/details/Range.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
|
||||
namespace cc {
|
||||
|
||||
template <class IteratorT>
|
||||
inline boost::iterator_range<IteratorT>
|
||||
makeRange(const std::pair<IteratorT, IteratorT> &p) noexcept { // NOLINT
|
||||
return boost::make_iterator_range(p.first, p.second);
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
493
cocos/renderer/pipeline/custom/details/SerializationUtils.h
Normal file
493
cocos/renderer/pipeline/custom/details/SerializationUtils.h
Normal file
@@ -0,0 +1,493 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <boost/container/flat_map.hpp>
|
||||
#include <boost/container/flat_set.hpp>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include "cocos/renderer/gfx-base/GFXDef-common.h"
|
||||
#include "cocos/renderer/pipeline/custom/ArchiveTypes.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace render {
|
||||
|
||||
// bool
|
||||
inline void save(OutputArchive& ar, const bool& v) {
|
||||
ar.writeBool(v);
|
||||
}
|
||||
|
||||
inline void load(InputArchive& ar, bool& v) {
|
||||
v = ar.readBool();
|
||||
}
|
||||
|
||||
// enum, integral, floating_point
|
||||
template <class T,
|
||||
std::enable_if_t<
|
||||
std::is_enum_v<T> || std::is_integral_v<T> || std::is_floating_point_v<T>,
|
||||
bool> = false>
|
||||
void save(OutputArchive& ar, const T& v) {
|
||||
static_assert(!std::is_enum_v<T> || sizeof(T) <= sizeof(uint32_t)); // enum can only be 1, 2, 4 bytes
|
||||
ar.writeNumber(static_cast<double>(v));
|
||||
}
|
||||
|
||||
template <class T,
|
||||
std::enable_if_t<
|
||||
std::is_integral_v<T> || std::is_floating_point_v<T>,
|
||||
bool> = false>
|
||||
void load(InputArchive& ar, T& v) {
|
||||
v = static_cast<T>(ar.readNumber());
|
||||
}
|
||||
|
||||
// Cast from double to enum might not be supported. _MSC_VER(1924)
|
||||
template <class T,
|
||||
std::enable_if_t<
|
||||
std::is_enum_v<T>,
|
||||
bool> = false>
|
||||
void load(InputArchive& ar, T& v) {
|
||||
v = static_cast<T>(static_cast<typename std::underlying_type<T>::type>(ar.readNumber()));
|
||||
}
|
||||
|
||||
// string
|
||||
template <class T, class Traits, class Allocator>
|
||||
void save(OutputArchive& ar, const std::basic_string<T, Traits, Allocator>& v) {
|
||||
ar.writeString(v);
|
||||
}
|
||||
|
||||
template <class T, class Traits, class Allocator>
|
||||
void load(InputArchive& ar, std::basic_string<T, Traits, Allocator>& v) {
|
||||
v = ar.readString();
|
||||
}
|
||||
|
||||
// vector
|
||||
template <class T, class Allocator>
|
||||
void save(OutputArchive& ar, const std::vector<T, Allocator>& vec) {
|
||||
save<uint32_t>(ar, static_cast<uint32_t>(vec.size()));
|
||||
for (const auto& v : vec) {
|
||||
save(ar, v);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T, class Allocator>
|
||||
void load(InputArchive& ar, std::vector<T, Allocator>& vec) {
|
||||
uint32_t sz = 0;
|
||||
load(ar, sz);
|
||||
vec.resize(sz);
|
||||
for (auto& v : vec) {
|
||||
load(ar, v);
|
||||
}
|
||||
}
|
||||
|
||||
// set
|
||||
template <class Value, class Less, class Allocator>
|
||||
void save(OutputArchive& ar, const std::set<Value, Less, Allocator>& set) {
|
||||
save<uint32_t>(ar, static_cast<uint32_t>(set.size()));
|
||||
for (const auto& value : set) {
|
||||
save(ar, value);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Value, class Less, class Allocator,
|
||||
std::enable_if_t<!std::uses_allocator_v<Value, Allocator>, bool> = false>
|
||||
void load(InputArchive& ar, std::set<Value, Less, Allocator>& set) {
|
||||
uint32_t sz = 0;
|
||||
load(ar, sz);
|
||||
for (uint32_t i = 0; i != sz; ++i) {
|
||||
Value value;
|
||||
load(ar, value);
|
||||
set.emplace(std::move(value));
|
||||
}
|
||||
}
|
||||
|
||||
template <class Value, class Less, class Allocator,
|
||||
std::enable_if_t<std::uses_allocator_v<Value, Allocator>, bool> = false>
|
||||
void load(InputArchive& ar, std::set<Value, Less, Allocator>& set) {
|
||||
uint32_t sz = 0;
|
||||
load(ar, sz);
|
||||
for (uint32_t i = 0; i != sz; ++i) {
|
||||
Value value(set.get_allocator());
|
||||
load(ar, value);
|
||||
set.emplace(std::move(value));
|
||||
}
|
||||
}
|
||||
|
||||
// flat_set
|
||||
template <class Value, class Less, class Allocator>
|
||||
void save(OutputArchive& ar, const boost::container::flat_set<Value, Less, Allocator>& set) {
|
||||
save<uint32_t>(ar, static_cast<uint32_t>(set.size()));
|
||||
for (const auto& value : set) {
|
||||
save(ar, value);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Value, class Less, class Allocator,
|
||||
std::enable_if_t<!std::uses_allocator_v<Value, Allocator>, bool> = false>
|
||||
void load(InputArchive& ar, boost::container::flat_set<Value, Less, Allocator>& set) {
|
||||
uint32_t sz = 0;
|
||||
load(ar, sz);
|
||||
set.reserve(sz);
|
||||
for (uint32_t i = 0; i != sz; ++i) {
|
||||
Value value;
|
||||
load(ar, value);
|
||||
set.emplace(std::move(value));
|
||||
}
|
||||
}
|
||||
|
||||
template <class Value, class Less, class Allocator,
|
||||
std::enable_if_t<std::uses_allocator_v<Value, Allocator>, bool> = false>
|
||||
void load(InputArchive& ar, boost::container::flat_set<Value, Less, Allocator>& set) {
|
||||
uint32_t sz = 0;
|
||||
load(ar, sz);
|
||||
set.reserve(sz);
|
||||
for (uint32_t i = 0; i != sz; ++i) {
|
||||
Value value(set.get_allocator());
|
||||
load(ar, value);
|
||||
set.emplace(std::move(value));
|
||||
}
|
||||
}
|
||||
|
||||
// unordered_set
|
||||
template <class Value, class Hash, class Pred, class Allocator>
|
||||
void save(OutputArchive& ar, const std::unordered_set<Value, Hash, Pred, Allocator>& set) {
|
||||
save<uint32_t>(ar, static_cast<uint32_t>(set.size()));
|
||||
for (const auto& value : set) {
|
||||
save(ar, value);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Value, class Hash, class Pred, class Allocator,
|
||||
std::enable_if_t<!std::uses_allocator_v<Value, Allocator>, bool> = false>
|
||||
void load(InputArchive& ar, std::unordered_set<Value, Hash, Pred, Allocator>& set) {
|
||||
uint32_t sz = 0;
|
||||
load(ar, sz);
|
||||
for (uint32_t i = 0; i != sz; ++i) {
|
||||
Value value;
|
||||
load(ar, value);
|
||||
set.emplace(std::move(value));
|
||||
}
|
||||
}
|
||||
|
||||
template <class Value, class Hash, class Pred, class Allocator,
|
||||
std::enable_if_t<std::uses_allocator_v<Value, Allocator>, bool> = false>
|
||||
void load(InputArchive& ar, std::unordered_set<Value, Hash, Pred, Allocator>& set) {
|
||||
uint32_t sz = 0;
|
||||
load(ar, sz);
|
||||
for (uint32_t i = 0; i != sz; ++i) {
|
||||
Value value(set.get_allocator());
|
||||
load(ar, value);
|
||||
set.emplace(std::move(value));
|
||||
}
|
||||
}
|
||||
|
||||
// map
|
||||
template <class Key, class Value, class Less, class Allocator>
|
||||
void save(OutputArchive& ar, const std::map<Key, Value, Less, Allocator>& map) {
|
||||
save<uint32_t>(ar, static_cast<uint32_t>(map.size()));
|
||||
for (const auto& [key, value] : map) {
|
||||
save(ar, key);
|
||||
save(ar, value);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Key, class Value, class Less, class Allocator,
|
||||
std::enable_if_t<!std::uses_allocator_v<Key, Allocator>, bool> = false,
|
||||
std::enable_if_t<!std::uses_allocator_v<Value, Allocator>, bool> = false>
|
||||
void load(InputArchive& ar, std::map<Key, Value, Less, Allocator>& map) {
|
||||
uint32_t sz = 0;
|
||||
load(ar, sz);
|
||||
for (uint32_t i = 0; i != sz; ++i) {
|
||||
Key key;
|
||||
Value value;
|
||||
load(ar, key);
|
||||
load(ar, value);
|
||||
map.emplace(std::move(key), std::move(value));
|
||||
}
|
||||
}
|
||||
|
||||
template <class Key, class Value, class Less, class Allocator,
|
||||
std::enable_if_t<std::uses_allocator_v<Key, Allocator>, bool> = false,
|
||||
std::enable_if_t<!std::uses_allocator_v<Value, Allocator>, bool> = false>
|
||||
void load(InputArchive& ar, std::map<Key, Value, Less, Allocator>& map) {
|
||||
uint32_t sz = 0;
|
||||
load(ar, sz);
|
||||
for (uint32_t i = 0; i != sz; ++i) {
|
||||
Key key(map.get_allocator());
|
||||
Value value;
|
||||
load(ar, key);
|
||||
load(ar, value);
|
||||
map.emplace(std::move(key), std::move(value));
|
||||
}
|
||||
}
|
||||
|
||||
template <class Key, class Value, class Less, class Allocator,
|
||||
std::enable_if_t<!std::uses_allocator_v<Key, Allocator>, bool> = false,
|
||||
std::enable_if_t<std::uses_allocator_v<Value, Allocator>, bool> = false>
|
||||
void load(InputArchive& ar, std::map<Key, Value, Less, Allocator>& map) {
|
||||
uint32_t sz = 0;
|
||||
load(ar, sz);
|
||||
for (uint32_t i = 0; i != sz; ++i) {
|
||||
Key key;
|
||||
Value value(map.get_allocator());
|
||||
load(ar, key);
|
||||
load(ar, value);
|
||||
map.emplace(std::move(key), std::move(value));
|
||||
}
|
||||
}
|
||||
|
||||
template <class Key, class Value, class Less, class Allocator,
|
||||
std::enable_if_t<std::uses_allocator_v<Key, Allocator>, bool> = false,
|
||||
std::enable_if_t<std::uses_allocator_v<Value, Allocator>, bool> = false>
|
||||
void load(InputArchive& ar, std::map<Key, Value, Less, Allocator>& map) {
|
||||
uint32_t sz = 0;
|
||||
load(ar, sz);
|
||||
for (uint32_t i = 0; i != sz; ++i) {
|
||||
Key key(map.get_allocator());
|
||||
Value value(map.get_allocator());
|
||||
load(ar, key);
|
||||
load(ar, value);
|
||||
map.emplace(std::move(key), std::move(value));
|
||||
}
|
||||
}
|
||||
|
||||
// flat_map
|
||||
template <class Key, class Value, class Less, class Allocator>
|
||||
void save(OutputArchive& ar, const boost::container::flat_map<Key, Value, Less, Allocator>& map) {
|
||||
save<uint32_t>(ar, static_cast<uint32_t>(map.size()));
|
||||
for (const auto& [key, value] : map) {
|
||||
save(ar, key);
|
||||
save(ar, value);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Key, class Value, class Less, class Allocator,
|
||||
std::enable_if_t<!std::uses_allocator_v<Key, Allocator>, bool> = false,
|
||||
std::enable_if_t<!std::uses_allocator_v<Value, Allocator>, bool> = false>
|
||||
void load(InputArchive& ar, boost::container::flat_map<Key, Value, Less, Allocator>& map) {
|
||||
uint32_t sz = 0;
|
||||
load(ar, sz);
|
||||
map.reserve(sz);
|
||||
for (uint32_t i = 0; i != sz; ++i) {
|
||||
Key key;
|
||||
Value value;
|
||||
load(ar, key);
|
||||
load(ar, value);
|
||||
map.emplace(std::move(key), std::move(value));
|
||||
}
|
||||
}
|
||||
|
||||
template <class Key, class Value, class Less, class Allocator,
|
||||
std::enable_if_t<std::uses_allocator_v<Key, Allocator>, bool> = false,
|
||||
std::enable_if_t<!std::uses_allocator_v<Value, Allocator>, bool> = false>
|
||||
void load(InputArchive& ar, boost::container::flat_map<Key, Value, Less, Allocator>& map) {
|
||||
uint32_t sz = 0;
|
||||
load(ar, sz);
|
||||
map.reserve(sz);
|
||||
for (uint32_t i = 0; i != sz; ++i) {
|
||||
Key key(map.get_allocator());
|
||||
Value value;
|
||||
load(ar, key);
|
||||
load(ar, value);
|
||||
map.emplace(std::move(key), std::move(value));
|
||||
}
|
||||
}
|
||||
|
||||
template <class Key, class Value, class Less, class Allocator,
|
||||
std::enable_if_t<!std::uses_allocator_v<Key, Allocator>, bool> = false,
|
||||
std::enable_if_t<std::uses_allocator_v<Value, Allocator>, bool> = false>
|
||||
void load(InputArchive& ar, boost::container::flat_map<Key, Value, Less, Allocator>& map) {
|
||||
uint32_t sz = 0;
|
||||
load(ar, sz);
|
||||
map.reserve(sz);
|
||||
for (uint32_t i = 0; i != sz; ++i) {
|
||||
Key key;
|
||||
Value value(map.get_allocator());
|
||||
load(ar, key);
|
||||
load(ar, value);
|
||||
map.emplace(std::move(key), std::move(value));
|
||||
}
|
||||
}
|
||||
|
||||
template <class Key, class Value, class Less, class Allocator,
|
||||
std::enable_if_t<std::uses_allocator_v<Key, Allocator>, bool> = false,
|
||||
std::enable_if_t<std::uses_allocator_v<Value, Allocator>, bool> = false>
|
||||
void load(InputArchive& ar, boost::container::flat_map<Key, Value, Less, Allocator>& map) {
|
||||
uint32_t sz = 0;
|
||||
load(ar, sz);
|
||||
map.reserve(sz);
|
||||
for (uint32_t i = 0; i != sz; ++i) {
|
||||
Key key(map.get_allocator());
|
||||
Value value(map.get_allocator());
|
||||
load(ar, key);
|
||||
load(ar, value);
|
||||
map.emplace(std::move(key), std::move(value));
|
||||
}
|
||||
}
|
||||
|
||||
// unordered_map
|
||||
template <class Key, class Value, class Hash, class Pred, class Allocator>
|
||||
void save(OutputArchive& ar, const std::unordered_map<Key, Value, Hash, Pred, Allocator>& map) {
|
||||
save<uint32_t>(ar, static_cast<uint32_t>(map.size()));
|
||||
for (const auto& [key, value] : map) {
|
||||
save(ar, key);
|
||||
save(ar, value);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Key, class Value, class Hash, class Pred, class Allocator,
|
||||
std::enable_if_t<!std::uses_allocator_v<Key, Allocator>, bool> = false,
|
||||
std::enable_if_t<!std::uses_allocator_v<Value, Allocator>, bool> = false>
|
||||
void load(InputArchive& ar, std::unordered_map<Key, Value, Hash, Pred, Allocator>& map) {
|
||||
uint32_t sz = 0;
|
||||
load(ar, sz);
|
||||
for (uint32_t i = 0; i != sz; ++i) {
|
||||
Key key;
|
||||
Value value;
|
||||
load(ar, key);
|
||||
load(ar, value);
|
||||
map.emplace(std::move(key), std::move(value));
|
||||
}
|
||||
}
|
||||
|
||||
template <class Key, class Value, class Hash, class Pred, class Allocator,
|
||||
std::enable_if_t<std::uses_allocator_v<Key, Allocator>, bool> = false,
|
||||
std::enable_if_t<!std::uses_allocator_v<Value, Allocator>, bool> = false>
|
||||
void load(InputArchive& ar, std::unordered_map<Key, Value, Hash, Pred, Allocator>& map) {
|
||||
uint32_t sz = 0;
|
||||
load(ar, sz);
|
||||
for (uint32_t i = 0; i != sz; ++i) {
|
||||
Key key(map.get_allocator());
|
||||
Value value;
|
||||
load(ar, key);
|
||||
load(ar, value);
|
||||
map.emplace(std::move(key), std::move(value));
|
||||
}
|
||||
}
|
||||
|
||||
template <class Key, class Value, class Hash, class Pred, class Allocator,
|
||||
std::enable_if_t<!std::uses_allocator_v<Key, Allocator>, bool> = false,
|
||||
std::enable_if_t<std::uses_allocator_v<Value, Allocator>, bool> = false>
|
||||
void load(InputArchive& ar, std::unordered_map<Key, Value, Hash, Pred, Allocator>& map) {
|
||||
uint32_t sz = 0;
|
||||
load(ar, sz);
|
||||
for (uint32_t i = 0; i != sz; ++i) {
|
||||
Key key;
|
||||
Value value(map.get_allocator());
|
||||
load(ar, key);
|
||||
load(ar, value);
|
||||
map.emplace(std::move(key), std::move(value));
|
||||
}
|
||||
}
|
||||
|
||||
template <class Key, class Value, class Hash, class Pred, class Allocator,
|
||||
std::enable_if_t<std::uses_allocator_v<Key, Allocator>, bool> = false,
|
||||
std::enable_if_t<std::uses_allocator_v<Value, Allocator>, bool> = false>
|
||||
void load(InputArchive& ar, std::unordered_map<Key, Value, Hash, Pred, Allocator>& map) {
|
||||
uint32_t sz = 0;
|
||||
load(ar, sz);
|
||||
for (uint32_t i = 0; i != sz; ++i) {
|
||||
Key key(map.get_allocator());
|
||||
Value value(map.get_allocator());
|
||||
load(ar, key);
|
||||
load(ar, value);
|
||||
map.emplace(std::move(key), std::move(value));
|
||||
}
|
||||
}
|
||||
|
||||
// gfx
|
||||
inline void save(OutputArchive& ar, const gfx::Color& v) {
|
||||
save(ar, v.x);
|
||||
save(ar, v.y);
|
||||
save(ar, v.z);
|
||||
save(ar, v.w);
|
||||
}
|
||||
|
||||
inline void load(InputArchive& ar, gfx::Color& v) {
|
||||
load(ar, v.x);
|
||||
load(ar, v.y);
|
||||
load(ar, v.z);
|
||||
load(ar, v.w);
|
||||
}
|
||||
|
||||
inline void save(OutputArchive& ar, const gfx::Uniform& v) {
|
||||
save(ar, v.name);
|
||||
save(ar, v.type);
|
||||
save(ar, v.count);
|
||||
}
|
||||
|
||||
inline void load(InputArchive& ar, gfx::Uniform& v) {
|
||||
load(ar, v.name);
|
||||
load(ar, v.type);
|
||||
load(ar, v.count);
|
||||
}
|
||||
|
||||
inline void save(OutputArchive& ar, const gfx::UniformBlock& v) {
|
||||
save(ar, v.set);
|
||||
save(ar, v.binding);
|
||||
save(ar, v.name);
|
||||
save(ar, v.members);
|
||||
save(ar, v.count);
|
||||
}
|
||||
|
||||
inline void load(InputArchive& ar, gfx::UniformBlock& v) {
|
||||
load(ar, v.set);
|
||||
load(ar, v.binding);
|
||||
load(ar, v.name);
|
||||
load(ar, v.members);
|
||||
load(ar, v.count);
|
||||
}
|
||||
|
||||
inline void save(OutputArchive& ar, const gfx::DescriptorSetLayoutBinding& v) {
|
||||
save(ar, v.binding);
|
||||
save(ar, v.descriptorType);
|
||||
save(ar, v.count);
|
||||
save(ar, v.stageFlags);
|
||||
// skip immutableSamplers: SamplerList
|
||||
}
|
||||
|
||||
inline void load(InputArchive& ar, gfx::DescriptorSetLayoutBinding& v) {
|
||||
load(ar, v.binding);
|
||||
load(ar, v.descriptorType);
|
||||
load(ar, v.count);
|
||||
load(ar, v.stageFlags);
|
||||
// skip immutableSamplers: SamplerList
|
||||
}
|
||||
|
||||
inline void save(OutputArchive& ar, const gfx::DescriptorSetLayoutInfo& v) {
|
||||
save(ar, v.bindings);
|
||||
}
|
||||
|
||||
inline void load(InputArchive& ar, gfx::DescriptorSetLayoutInfo& v) {
|
||||
load(ar, v.bindings);
|
||||
}
|
||||
|
||||
} // namespace render
|
||||
|
||||
} // namespace cc
|
||||
102
cocos/renderer/pipeline/custom/details/Set.h
Normal file
102
cocos/renderer/pipeline/custom/details/Set.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <boost/container/flat_set.hpp>
|
||||
#include <boost/container/pmr/flat_set.hpp>
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
#include "cocos/base/std/hash/hash_fwd.hpp"
|
||||
#include "cocos/renderer/pipeline/custom/details/Utility.h"
|
||||
|
||||
// for std::less<> the transparent comparator
|
||||
// see https://stackoverflow.com/questions/20317413/what-are-transparent-comparators
|
||||
|
||||
namespace cc {
|
||||
|
||||
// set
|
||||
template <class Value>
|
||||
using TransparentSet = std::set<Value, std::less<>>;
|
||||
|
||||
template <class Value>
|
||||
using TransparentMultiSet = std::multiset<Value, std::less<>>;
|
||||
|
||||
template <class Value>
|
||||
using PmrTransparentSet = std::set<
|
||||
Value, std::less<>,
|
||||
boost::container::pmr::polymorphic_allocator<Value>>;
|
||||
|
||||
template <class Value>
|
||||
using PmrTransparentMultiSet = std::multiset<
|
||||
Value, std::less<>,
|
||||
boost::container::pmr::polymorphic_allocator<Value>>;
|
||||
|
||||
// flat_set
|
||||
template <class Value>
|
||||
using FlatSet = boost::container::flat_set<Value, std::less<>>;
|
||||
|
||||
template <class Value>
|
||||
using FlatMultiSet = boost::container::flat_multiset<Value, std::less<>>;
|
||||
|
||||
template <class Value>
|
||||
using PmrFlatSet = boost::container::pmr::flat_set<Value, std::less<>>;
|
||||
|
||||
template <class Value>
|
||||
using PmrFlatMultiSet = boost::container::pmr::flat_multiset<Value, std::less<>>;
|
||||
|
||||
// unordered_set
|
||||
template <class Value>
|
||||
using PmrUnorderedSet = std::unordered_set<
|
||||
Value, ccstd::hash<Value>, std::equal_to<Value>,
|
||||
boost::container::pmr::polymorphic_allocator<Value>>;
|
||||
|
||||
template <class Value>
|
||||
using PmrUnorderedMultiSet = std::unordered_multiset<
|
||||
Value, ccstd::hash<Value>, std::equal_to<Value>,
|
||||
boost::container::pmr::polymorphic_allocator<Value>>;
|
||||
|
||||
// transparent string unordered_set
|
||||
template <class Value>
|
||||
using UnorderedStringSet = std::unordered_set<
|
||||
Value,
|
||||
TransparentStringHash<typename Value::value_type>, std::equal_to<>>;
|
||||
|
||||
template <class Value>
|
||||
using UnorderedStringMultiSet = std::unordered_multiset<
|
||||
Value,
|
||||
TransparentStringHash<typename Value::value_type>, std::equal_to<>>;
|
||||
|
||||
template <class Value>
|
||||
using PmrUnorderedStringSet = std::unordered_set<
|
||||
Value,
|
||||
TransparentStringHash<typename Value::value_type>, std::equal_to<>,
|
||||
boost::container::pmr::polymorphic_allocator<Value>>;
|
||||
|
||||
template <class Value>
|
||||
using PmrUnorderedStringMultiSet = std::unordered_multiset<
|
||||
Value,
|
||||
TransparentStringHash<typename Value::value_type>, std::equal_to<>,
|
||||
boost::container::pmr::polymorphic_allocator<Value>>;
|
||||
|
||||
} // namespace cc
|
||||
61
cocos/renderer/pipeline/custom/details/Utility.h
Normal file
61
cocos/renderer/pipeline/custom/details/Utility.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <string_view>
|
||||
|
||||
// transparent hash
|
||||
// see https://stackoverflow.com/questions/20317413/what-are-transparent-comparators
|
||||
|
||||
namespace cc {
|
||||
|
||||
template <class Char>
|
||||
struct TransparentStringHash {
|
||||
using is_transparent = void;
|
||||
using string_view_type = std::basic_string_view<Char>;
|
||||
|
||||
size_t operator()(string_view_type str) const noexcept {
|
||||
return boost::hash<string_view_type>{}(str);
|
||||
}
|
||||
size_t operator()(const Char* str) const noexcept {
|
||||
return boost::hash<string_view_type>{}(str);
|
||||
}
|
||||
template <class Alloc>
|
||||
size_t operator()(const std::basic_string<Char, std::char_traits<Char>, Alloc>& str) const noexcept {
|
||||
return boost::hash<string_view_type>{}(str);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Char>
|
||||
struct TransparentStringEqual {
|
||||
using is_transparent = void;
|
||||
using string_view_type = std::basic_string_view<Char>;
|
||||
template <class T, class U>
|
||||
bool operator()(T&& lhs, U&& rhs) const noexcept {
|
||||
return string_view_type{lhs} == string_view_type{rhs};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
Reference in New Issue
Block a user