no message

This commit is contained in:
gem
2025-02-18 15:21:31 +08:00
commit 2d133e56d7
1980 changed files with 465595 additions and 0 deletions

View 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)

View 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

View 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

View 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

View 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

View 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;
}

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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