From e4b333a531a0da398eac94c93cab14921e3eda5b Mon Sep 17 00:00:00 2001 From: zhouhang95 <765229842@qq.com> Date: Mon, 21 Oct 2024 21:20:54 +0800 Subject: [PATCH 1/7] uuid_v4 --- zeno/tpls/include/endianness.h | 157 +++++++++++++++++++ zeno/tpls/include/uuid_v4.h | 276 +++++++++++++++++++++++++++++++++ 2 files changed, 433 insertions(+) create mode 100644 zeno/tpls/include/endianness.h create mode 100644 zeno/tpls/include/uuid_v4.h diff --git a/zeno/tpls/include/endianness.h b/zeno/tpls/include/endianness.h new file mode 100644 index 0000000000..5a80e1d25f --- /dev/null +++ b/zeno/tpls/include/endianness.h @@ -0,0 +1,157 @@ +#pragma once + +#if defined(__GLIBC__) || defined(__GNU_LIBRARY__) || defined(__ANDROID__) + #include +#elif defined(__APPLE__) && defined(__MACH__) + #include +#elif defined(BSD) || defined(_SYSTYPE_BSD) + #if defined(__OpenBSD__) + #include + #else + #include + #endif +#endif + +#if defined(__BYTE_ORDER) + #if defined(__BIG_ENDIAN) && (__BYTE_ORDER == __BIG_ENDIAN) + #define BIGENDIAN + #elif defined(__LITTLE_ENDIAN) && (__BYTE_ORDER == __LITTLE_ENDIAN) + #define LITTLEENDIAN + #endif +#elif defined(_BYTE_ORDER) + #if defined(_BIG_ENDIAN) && (_BYTE_ORDER == _BIG_ENDIAN) + #define BIGENDIAN + #elif defined(_LITTLE_ENDIAN) && (_BYTE_ORDER == _LITTLE_ENDIAN) + #define LITTLEENDIAN + #endif +#elif defined(__BIG_ENDIAN__) + #define BIGENDIAN +#elif defined(__LITTLE_ENDIAN__) + #define LITTLEENDIAN +#else + #if defined(__ARMEL__) || \ + defined(__THUMBEL__) || \ + defined(__AARCH64EL__) || \ + defined(_MIPSEL) || \ + defined(__MIPSEL) || \ + defined(__MIPSEL__) || \ + defined(__ia64__) || defined(_IA64) || \ + defined(__IA64__) || defined(__ia64) || \ + defined(_M_IA64) || defined(__itanium__) || \ + defined(i386) || defined(__i386__) || \ + defined(__i486__) || defined(__i586__) || \ + defined(__i686__) || defined(__i386) || \ + defined(_M_IX86) || defined(_X86_) || \ + defined(__THW_INTEL__) || defined(__I86__) || \ + defined(__INTEL__) || \ + defined(__x86_64) || defined(__x86_64__) || \ + defined(__amd64__) || defined(__amd64) || \ + defined(_M_X64) || \ + defined(__bfin__) || defined(__BFIN__) || \ + defined(bfin) || defined(BFIN) + + #define LITTLEENDIAN + #elif defined(__m68k__) || defined(M68000) || \ + defined(__hppa__) || defined(__hppa) || defined(__HPPA__) || \ + defined(__sparc__) || defined(__sparc) || \ + defined(__370__) || defined(__THW_370__) || \ + defined(__s390__) || defined(__s390x__) || \ + defined(__SYSC_ZARCH__) + + #define BIGENDIAN + + #elif defined(__arm__) || defined(__arm64) || defined(__thumb__) || \ + defined(__TARGET_ARCH_ARM) || defined(__TARGET_ARCH_THUMB) || \ + defined(__ARM_ARCH) || \ + defined(_M_ARM) || defined(_M_ARM64) + + #if defined(_WIN32) || defined(_WIN64) || \ + defined(__WIN32__) || defined(__TOS_WIN__) || \ + defined(__WINDOWS__) + + #define LITTLEENDIAN + + #else + #error "Cannot determine system endianness." + #endif + #endif +#endif + + +#if defined(BIGENDIAN) + // Try to use compiler intrinsics + #if defined(__INTEL_COMPILER) || defined(__ICC) + #define betole16(x) _bswap16(x) + #define betole32(x) _bswap(x) + #define betole64(x) _bswap64(x) + #elif defined(__GNUC__) // GCC and CLANG + #define betole16(x) __builtin_bswap16(x) + #define betole32(x) __builtin_bswap32(x) + #define betole64(x) __builtin_bswap64(x) + #elif defined(_MSC_VER) // MSVC + #include + #define betole16(x) _byteswap_ushort(x) + #define betole32(x) _byteswap_ulong(x) + #define betole64(x) _byteswap_uint64(x) + #else + #define FALLBACK_SWAP + #define betole16(x) swap_u16(x) + #define betole32(x) swap_u32(x) + #define betole64(x) swap_u64(x) + #endif + #define betole128(x) swap_u128(x) + #define betole256(x) swap_u256(x) +#else + #define betole16(x) (x) + #define betole32(x) (x) + #define betole64(x) (x) + #define betole128(x) (x) + #define betole256(x) (x) +#endif // BIGENDIAN + +#if defined(BIGENDIAN) + #include + #include + #include + #include + + inline __m128i swap_u128(__m128i value) { + const __m128i shuffle = _mm_set_epi64x(0x0001020304050607, 0x08090a0b0c0d0e0f); + return _mm_shuffle_epi8(value, shuffle); + } + + inline __m256i swap_u256(__m256i value) { + const __m256i shuffle = _mm256_set_epi64x(0x0001020304050607, 0x08090a0b0c0d0e0f, 0x0001020304050607, 0x08090a0b0c0d0e0f); + return _mm256_shuffle_epi8(value, shuffle); + } +#endif // BIGENDIAN + +#if defined(FALLBACK_SWAP) + #include + inline uint16_t swap_u16(uint16_t value) + { + return + ((value & 0xFF00u) >> 8u) | + ((value & 0x00FFu) << 8u); + } + inline uint32_t swap_u32(uint32_t value) + { + return + ((value & 0xFF000000u) >> 24u) | + ((value & 0x00FF0000u) >> 8u) | + ((value & 0x0000FF00u) << 8u) | + ((value & 0x000000FFu) << 24u); + } + inline uint64_t swap_u64(uint64_t value) + { + return + ((value & 0xFF00000000000000u) >> 56u) | + ((value & 0x00FF000000000000u) >> 40u) | + ((value & 0x0000FF0000000000u) >> 24u) | + ((value & 0x000000FF00000000u) >> 8u) | + ((value & 0x00000000FF000000u) << 8u) | + ((value & 0x0000000000FF0000u) << 24u) | + ((value & 0x000000000000FF00u) << 40u) | + ((value & 0x00000000000000FFu) << 56u); + } +#endif // FALLBACK_SWAP diff --git a/zeno/tpls/include/uuid_v4.h b/zeno/tpls/include/uuid_v4.h new file mode 100644 index 0000000000..ed444984aa --- /dev/null +++ b/zeno/tpls/include/uuid_v4.h @@ -0,0 +1,276 @@ +/* +MIT License + +Copyright (c) 2018 Xavier "Crashoz" Launey +*/ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "endianness.h" + +namespace UUIDv4 { + +/* + Converts a 128-bits unsigned int to an UUIDv4 string representation. + Uses SIMD via Intel's AVX2 instruction set. + */ +void inline m128itos(__m128i x, char* mem) { + // Expand each byte in x to two bytes in res + // i.e. 0x12345678 -> 0x0102030405060708 + // Then translate each byte to its hex ascii representation + // i.e. 0x0102030405060708 -> 0x3132333435363738 + const __m256i mask = _mm256_set1_epi8(0x0F); + const __m256i add = _mm256_set1_epi8(0x06); + const __m256i alpha_mask = _mm256_set1_epi8(0x10); + const __m256i alpha_offset = _mm256_set1_epi8(0x57); + + __m256i a = _mm256_castsi128_si256(x); + __m256i as = _mm256_srli_epi64(a, 4); + __m256i lo = _mm256_unpacklo_epi8(as, a); + __m128i hi = _mm256_castsi256_si128(_mm256_unpackhi_epi8(as, a)); + __m256i c = _mm256_inserti128_si256(lo, hi, 1); + __m256i d = _mm256_and_si256(c, mask); + __m256i alpha = _mm256_slli_epi64(_mm256_and_si256(_mm256_add_epi8(d, add), alpha_mask), 3); + __m256i offset = _mm256_blendv_epi8(_mm256_slli_epi64(add, 3), alpha_offset, alpha); + __m256i res = _mm256_add_epi8(d, offset); + + // Add dashes between blocks as specified in RFC-4122 + // 8-4-4-4-12 + const __m256i dash_shuffle = _mm256_set_epi32(0x0b0a0908, 0x07060504, 0x80030201, 0x00808080, 0x0d0c800b, 0x0a090880, 0x07060504, 0x03020100); + const __m256i dash = _mm256_set_epi64x(0x0000000000000000ull, 0x2d000000002d0000ull, 0x00002d000000002d, 0x0000000000000000ull); + + __m256i resd = _mm256_shuffle_epi8(res, dash_shuffle); + resd = _mm256_or_si256(resd, dash); + + _mm256_storeu_si256((__m256i*)mem, betole256(resd)); + *(uint16_t*)(mem+16) = betole16(_mm256_extract_epi16(res, 7)); + *(uint32_t*)(mem+32) = betole32(_mm256_extract_epi32(res, 7)); +} + +/* + Converts an UUIDv4 string representation to a 128-bits unsigned int. + Uses SIMD via Intel's AVX2 instruction set. + */ +__m128i inline stom128i(const char* mem) { + // Remove dashes and pack hex ascii bytes in a 256-bits int + const __m256i dash_shuffle = _mm256_set_epi32(0x80808080, 0x0f0e0d0c, 0x0b0a0908, 0x06050403, 0x80800f0e, 0x0c0b0a09, 0x07060504, 0x03020100); + + __m256i x = betole256(_mm256_loadu_si256((__m256i*)mem)); + x = _mm256_shuffle_epi8(x, dash_shuffle); + x = _mm256_insert_epi16(x, betole16(*(uint16_t*)(mem+16)), 7); + x = _mm256_insert_epi32(x, betole32(*(uint32_t*)(mem+32)), 7); + + // Build a mask to apply a different offset to alphas and digits + const __m256i sub = _mm256_set1_epi8(0x2F); + const __m256i mask = _mm256_set1_epi8(0x20); + const __m256i alpha_offset = _mm256_set1_epi8(0x28); + const __m256i digits_offset = _mm256_set1_epi8(0x01); + const __m256i unweave = _mm256_set_epi32(0x0f0d0b09, 0x0e0c0a08, 0x07050301, 0x06040200, 0x0f0d0b09, 0x0e0c0a08, 0x07050301, 0x06040200); + const __m256i shift = _mm256_set_epi32(0x00000000, 0x00000004, 0x00000000, 0x00000004, 0x00000000, 0x00000004, 0x00000000, 0x00000004); + + // Translate ascii bytes to their value + // i.e. 0x3132333435363738 -> 0x0102030405060708 + // Shift hi-digits + // i.e. 0x0102030405060708 -> 0x1002300450067008 + // Horizontal add + // i.e. 0x1002300450067008 -> 0x12345678 + __m256i a = _mm256_sub_epi8(x, sub); + __m256i alpha = _mm256_slli_epi64(_mm256_and_si256(a, mask), 2); + __m256i sub_mask = _mm256_blendv_epi8(digits_offset, alpha_offset, alpha); + a = _mm256_sub_epi8(a, sub_mask); + a = _mm256_shuffle_epi8(a, unweave); + a = _mm256_sllv_epi32(a, shift); + a = _mm256_hadd_epi32(a, _mm256_setzero_si256()); + a = _mm256_permute4x64_epi64(a, 0b00001000); + + return _mm256_castsi256_si128(a); +} + +/* + * UUIDv4 (random 128-bits) RFC-4122 + */ +class UUID { + public: + UUID() + {} + + UUID(const UUID &other) { + __m128i x = _mm_load_si128((__m128i*)other.data); + _mm_store_si128((__m128i*)data, x); + } + + /* Builds a 128-bits UUID */ + UUID(__m128i uuid) { + _mm_store_si128((__m128i*)data, uuid); + } + + UUID(uint64_t x, uint64_t y) { + __m128i z = _mm_set_epi64x(x, y); + _mm_store_si128((__m128i*)data, z); + } + + UUID(const uint8_t* bytes) { + __m128i x = _mm_loadu_si128((__m128i*)bytes); + _mm_store_si128((__m128i*)data, x); + } + + /* Builds an UUID from a byte string (16 bytes long) */ + explicit UUID(const std::string &bytes) { + __m128i x = betole128(_mm_loadu_si128((__m128i*)bytes.data())); + _mm_store_si128((__m128i*)data, x); + } + + /* Static factory to parse an UUID from its string representation */ + static UUID fromStrFactory(const std::string &s) { + return fromStrFactory(s.c_str()); + } + + static UUID fromStrFactory(const char* raw) { + return UUID(stom128i(raw)); + } + + void fromStr(const char* raw) { + _mm_store_si128((__m128i*)data, stom128i(raw)); + } + + UUID& operator=(const UUID &other) { + if (&other == this) { + return *this; + } + __m128i x = _mm_load_si128((__m128i*)other.data); + _mm_store_si128((__m128i*)data, x); + return *this; + } + + friend bool operator==(const UUID &lhs, const UUID &rhs) { + __m128i x = _mm_load_si128((__m128i*)lhs.data); + __m128i y = _mm_load_si128((__m128i*)rhs.data); + + __m128i neq = _mm_xor_si128(x, y); + return _mm_test_all_zeros(neq, neq); + } + + friend bool operator<(const UUID &lhs, const UUID &rhs) { + // There are no trivial 128-bits comparisons in SSE/AVX + // It's faster to compare two uint64_t + uint64_t *x = (uint64_t*)lhs.data; + uint64_t *y = (uint64_t*)rhs.data; + return *x < *y || (*x == *y && *(x + 1) < *(y + 1)); + } + + friend bool operator!=(const UUID &lhs, const UUID &rhs) { return !(lhs == rhs); } + friend bool operator> (const UUID &lhs, const UUID &rhs) { return rhs < lhs; } + friend bool operator<=(const UUID &lhs, const UUID &rhs) { return !(lhs > rhs); } + friend bool operator>=(const UUID &lhs, const UUID &rhs) { return !(lhs < rhs); } + + /* Serializes the uuid to a byte string (16 bytes) */ + std::string bytes() const { + std::string mem; + bytes(mem); + return mem; + } + + void bytes(std::string &out) const { + out.resize(sizeof(data)); + bytes((char*)out.data()); + } + + void bytes(char* bytes) const { + __m128i x = betole128(_mm_load_si128((__m128i*)data)); + _mm_storeu_si128((__m128i*)bytes, x); + } + + /* Converts the uuid to its string representation */ + std::string str() const { + std::string mem; + str(mem); + return mem; + } + + void str(std::string &s) const { + s.resize(36); + str((char*)s.data()); + } + + void str(char *res) const { + __m128i x = _mm_load_si128((__m128i*)data); + m128itos(x, res); + } + + friend std::ostream& operator<< (std::ostream& stream, const UUID& uuid) { + return stream << uuid.str(); + } + + friend std::istream& operator>> (std::istream& stream, UUID& uuid) { + std::string s; + stream >> s; + uuid = fromStrFactory(s); + return stream; + } + + size_t hash() const { + const uint64_t a = *((uint64_t*)data); + const uint64_t b = *((uint64_t*)&data[8]); + return a ^ (b + 0x9e3779b9 + (a << 6) + (a >> 2)); + } + + private: + alignas(128) uint8_t data[16]; +}; + +/* + Generates UUIDv4 from a provided random generator (c++11 module) + std::mt19937_64 is highly recommended as it has a SIMD implementation that + makes it very fast and it produces high quality randomness. + */ +template +class UUIDGenerator { + public: + UUIDGenerator() : generator(new RNG(std::random_device()())), distribution(std::numeric_limits::min(), std::numeric_limits::max()) + {} + + UUIDGenerator(uint64_t seed) : generator(new RNG(seed)), distribution(std::numeric_limits::min(), std::numeric_limits::max()) + {} + + UUIDGenerator(RNG &gen) : generator(gen), distribution(std::numeric_limits::min(), std::numeric_limits::max()) + {} + + /* Generates a new UUID */ + UUID getUUID() { + // The two masks set the uuid version (4) and variant (1) + const __m128i and_mask = _mm_set_epi64x(0xFFFFFFFFFFFFFF3Full, 0xFF0FFFFFFFFFFFFFull); + const __m128i or_mask = _mm_set_epi64x(0x0000000000000080ull, 0x0040000000000000ull); + __m128i n = _mm_set_epi64x(distribution(*generator), distribution(*generator)); + __m128i uuid = _mm_or_si128(_mm_and_si128(n, and_mask), or_mask); + + return UUID(uuid); + } + + private: + std::shared_ptr generator; + std::uniform_int_distribution distribution; +}; + +} + +namespace std { + template <> struct hash + { + size_t operator()(const UUIDv4::UUID & uuid) const + { + return uuid.hash(); + } + }; +} From 8fa5a5a334823bd185197d5257d90c13dd8489d6 Mon Sep 17 00:00:00 2001 From: zhouhang95 <765229842@qq.com> Date: Tue, 22 Oct 2024 12:42:43 +0800 Subject: [PATCH 2/7] WIP --- zeno/src/nodes/JsonProcess.cpp | 97 ++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/zeno/src/nodes/JsonProcess.cpp b/zeno/src/nodes/JsonProcess.cpp index 0518ab6e3a..08a1e57ca4 100644 --- a/zeno/src/nodes/JsonProcess.cpp +++ b/zeno/src/nodes/JsonProcess.cpp @@ -12,6 +12,7 @@ #include #include #include +#include "uuid_v4.h" using Json = nlohmann::json; @@ -667,4 +668,100 @@ ZENDEFNODE(JsonGetData, { }, }); +struct CreateRenderInstance : zeno::INode { + virtual void apply() override { + auto instID = get_input2("instID"); + auto Geom = get_input2("Geom"); + auto Matrix = get_input2("Matrix"); + auto Material = get_input2("Material"); + + auto out_json = std::make_shared(); + out_json->json["BasicRenderInstances"][instID] = { + {"Geom", Geom}, + {"Matrix", Matrix}, + {"Material", Material}, + }; + set_output("json", out_json); + } +}; + +ZENDEFNODE( CreateRenderInstance, { + { + {"string", "instID", ""}, + {"string", "Geom", ""}, + {"string", "Matrix", "Identity"}, + {"string", "Material", "Default"}, + }, + { + {"json"}, + }, + {}, + { + "shader", + }, +}); +struct RenderGroup : zeno::INode { + virtual void apply() override { + auto is_static = get_input2("static"); + auto Matrix = get_input2("Matrix"); + + auto items = get_input("items")->get(); + + UUIDv4::UUIDGenerator uuidGenerator; + UUIDv4::UUID uuid = uuidGenerator.getUUID(); + std::string s = uuid.str(); + + auto out_json = std::make_shared(); + out_json->json["BasicRenderInstances"] = {}; + auto &bri = out_json->json["BasicRenderInstances"]; + int static_group_count = 0; + int dynamic_group_count = 0; + for (const auto& item: items) { + if (item->json.contains("StaticRenderGroups")) { + static_group_count += 1; + } + if (item->json.contains("DynamicRenderGroups")) { + dynamic_group_count += 1; + } + } + + for (const auto& item: items) { + for (auto& [key, value] : item->json["BasicRenderInstances"].items()) { + if (bri.contains(key)) { + auto log = zeno::format("Error: Instance {} already exists", key); + log_error(log); + throw zeno::makeError(log); + } + bri[key] = value; + } + if (static_group_count == 0 && dynamic_group_count == 0) { + if (is_static) { + auto & sRenderGroup0 = out_json->json["StaticRenderGroups"]["sRenderGroup0"]; + if (sRenderGroup0.contains("Matrixes") == false) { + + } + } + + } + } + + set_output("json", out_json); + } +}; + +ZENDEFNODE( RenderGroup, { + { + {"list", "items"}, + {"bool", "static", "1"}, + {"string", "Matrixes", "Identity"}, + }, + { + {"json"}, + }, + {}, + { + "shader", + }, +}); + } \ No newline at end of file From 7ae8772b16015e11e4ec972ff1919e28537d145c Mon Sep 17 00:00:00 2001 From: zhouhang95 <765229842@qq.com> Date: Wed, 23 Oct 2024 20:12:04 +0800 Subject: [PATCH 3/7] WIP --- zeno/src/nodes/JsonProcess.cpp | 50 ++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/zeno/src/nodes/JsonProcess.cpp b/zeno/src/nodes/JsonProcess.cpp index 08a1e57ca4..ff99992565 100644 --- a/zeno/src/nodes/JsonProcess.cpp +++ b/zeno/src/nodes/JsonProcess.cpp @@ -676,7 +676,7 @@ struct CreateRenderInstance : zeno::INode { auto Material = get_input2("Material"); auto out_json = std::make_shared(); - out_json->json["BasicRenderInstances"][instID] = { + out_json->json["BasicRenderInstance"][instID] = { {"Geom", Geom}, {"Matrix", Matrix}, {"Material", Material}, @@ -703,7 +703,8 @@ ZENDEFNODE( CreateRenderInstance, { struct RenderGroup : zeno::INode { virtual void apply() override { auto is_static = get_input2("static"); - auto Matrix = get_input2("Matrix"); + auto Matrix_string = get_input2("Matrixes"); + std::vector Matrixes = zeno::split_str(Matrix_string, {' ', '\n'}); auto items = get_input("items")->get(); @@ -713,35 +714,44 @@ struct RenderGroup : zeno::INode { auto out_json = std::make_shared(); out_json->json["BasicRenderInstances"] = {}; - auto &bri = out_json->json["BasicRenderInstances"]; - int static_group_count = 0; - int dynamic_group_count = 0; - for (const auto& item: items) { - if (item->json.contains("StaticRenderGroups")) { - static_group_count += 1; - } - if (item->json.contains("DynamicRenderGroups")) { - dynamic_group_count += 1; - } - } + auto &bris = out_json->json["BasicRenderInstances"]; for (const auto& item: items) { - for (auto& [key, value] : item->json["BasicRenderInstances"].items()) { - if (bri.contains(key)) { + for (auto& [key, value] : item->json["BasicRenderInstance"].items()) { + if (bris.contains(key)) { auto log = zeno::format("Error: Instance {} already exists", key); log_error(log); throw zeno::makeError(log); } - bri[key] = value; - } - if (static_group_count == 0 && dynamic_group_count == 0) { + bris[key] = value; if (is_static) { auto & sRenderGroup0 = out_json->json["StaticRenderGroups"]["sRenderGroup0"]; + if (sRenderGroup0.contains("Objects") == false) { + sRenderGroup0["Objects"] = Json::array(); + } + sRenderGroup0["Objects"].push_back(key); if (sRenderGroup0.contains("Matrixes") == false) { - + Json jsonArray = Json::array(); + for (auto &matrix: Matrixes) { + jsonArray.push_back(matrix); + } + sRenderGroup0["Matrixes"] = jsonArray; + } + } + else { + auto & dRenderGroup0 = out_json->json["DynamicRenderGroups"]["dRenderGroup0"]; + if (dRenderGroup0.contains("Objects") == false) { + dRenderGroup0["Objects"] = Json::array(); + } + dRenderGroup0["Objects"].push_back(key); + if (dRenderGroup0.contains("Matrixes") == false) { + Json jsonArray = Json::array(); + for (auto &matrix: Matrixes) { + jsonArray.push_back(matrix); + } + dRenderGroup0["Matrixes"] = jsonArray; } } - } } From 59c68200e47cafa2a08e910a559e5d163c88c3a3 Mon Sep 17 00:00:00 2001 From: zhouhang95 <765229842@qq.com> Date: Tue, 29 Oct 2024 19:49:56 +0800 Subject: [PATCH 4/7] WIP --- zeno/src/nodes/JsonProcess.cpp | 94 +++++++---- zeno/tpls/include/endianness.h | 157 ------------------- zeno/tpls/include/uuid_v4.h | 276 --------------------------------- 3 files changed, 61 insertions(+), 466 deletions(-) delete mode 100644 zeno/tpls/include/endianness.h delete mode 100644 zeno/tpls/include/uuid_v4.h diff --git a/zeno/src/nodes/JsonProcess.cpp b/zeno/src/nodes/JsonProcess.cpp index ff99992565..e81e2f7ee1 100644 --- a/zeno/src/nodes/JsonProcess.cpp +++ b/zeno/src/nodes/JsonProcess.cpp @@ -7,12 +7,10 @@ #include "zeno/utils/fileio.h" #include "zeno/utils/log.h" #include "zeno/utils/string.h" -#include #include #include #include #include -#include "uuid_v4.h" using Json = nlohmann::json; @@ -674,6 +672,10 @@ struct CreateRenderInstance : zeno::INode { auto Geom = get_input2("Geom"); auto Matrix = get_input2("Matrix"); auto Material = get_input2("Material"); + if (instID.empty()) { + auto info = zeno::format("instID {} can not be empty!", instID); + throw zeno::makeError(info); + } auto out_json = std::make_shared(); out_json->json["BasicRenderInstance"][instID] = { @@ -702,54 +704,79 @@ ZENDEFNODE( CreateRenderInstance, { }); struct RenderGroup : zeno::INode { virtual void apply() override { + auto RenderGroupID = get_input2("RenderGroupID"); auto is_static = get_input2("static"); auto Matrix_string = get_input2("Matrixes"); std::vector Matrixes = zeno::split_str(Matrix_string, {' ', '\n'}); auto items = get_input("items")->get(); - - UUIDv4::UUIDGenerator uuidGenerator; - UUIDv4::UUID uuid = uuidGenerator.getUUID(); - std::string s = uuid.str(); + // Check group id not duplicated + { + if (RenderGroupID.empty()) { + auto info = zeno::format("RenderGroupID {} can not be empty!", RenderGroupID); + throw zeno::makeError(info); + } + for (const auto& item: items) { + if (item->json.contains("BasicRenderInstance")) { + for (auto& [key, _] : item->json["BasicRenderInstance"].items()) { + if (key == RenderGroupID) { + auto info = zeno::format("RenderGroupID {} can not be duplicated!", RenderGroupID); + throw zeno::makeError(info); + } + } + } + if (item->json.contains("BasicRenderInstances")) { + for (auto& [key, _] : item->json["BasicRenderInstances"].items()) { + if (key == RenderGroupID) { + auto info = zeno::format("RenderGroupID {} can not be duplicated!", RenderGroupID); + throw zeno::makeError(info); + } + } + } + if (item->json.contains("StaticRenderGroups")) { + for (auto& [key, _] : item->json["StaticRenderGroups"].items()) { + if (key == RenderGroupID) { + auto info = zeno::format("RenderGroupID {} can not be duplicated!", RenderGroupID); + throw zeno::makeError(info); + } + } + } + if (item->json.contains("DynamicRenderGroups")) { + for (auto& [key, _] : item->json["DynamicRenderGroups"].items()) { + if (key == RenderGroupID) { + auto info = zeno::format("RenderGroupID {} can not be duplicated!", RenderGroupID); + throw zeno::makeError(info); + } + } + } + } + } auto out_json = std::make_shared(); out_json->json["BasicRenderInstances"] = {}; auto &bris = out_json->json["BasicRenderInstances"]; for (const auto& item: items) { - for (auto& [key, value] : item->json["BasicRenderInstance"].items()) { - if (bris.contains(key)) { - auto log = zeno::format("Error: Instance {} already exists", key); - log_error(log); - throw zeno::makeError(log); - } - bris[key] = value; - if (is_static) { - auto & sRenderGroup0 = out_json->json["StaticRenderGroups"]["sRenderGroup0"]; - if (sRenderGroup0.contains("Objects") == false) { - sRenderGroup0["Objects"] = Json::array(); - } - sRenderGroup0["Objects"].push_back(key); - if (sRenderGroup0.contains("Matrixes") == false) { - Json jsonArray = Json::array(); - for (auto &matrix: Matrixes) { - jsonArray.push_back(matrix); - } - sRenderGroup0["Matrixes"] = jsonArray; + if (item->json.contains("BasicRenderInstance")) { + for (auto& [key, value] : item->json["BasicRenderInstance"].items()) { + if (bris.contains(key)) { + auto log = zeno::format("Error: Instance {} already exists", key); + log_error(log); + throw zeno::makeError(log); } - } - else { - auto & dRenderGroup0 = out_json->json["DynamicRenderGroups"]["dRenderGroup0"]; - if (dRenderGroup0.contains("Objects") == false) { - dRenderGroup0["Objects"] = Json::array(); + bris[key] = value; + auto category = is_static ? "StaticRenderGroups" : "DynamicRenderGroups"; + auto & RenderGroup0 = out_json->json[category][RenderGroupID]; + if (RenderGroup0.contains("Objects") == false) { + RenderGroup0["Objects"] = Json::array(); } - dRenderGroup0["Objects"].push_back(key); - if (dRenderGroup0.contains("Matrixes") == false) { + RenderGroup0["Objects"].push_back(key); + if (RenderGroup0.contains("Matrixes") == false) { Json jsonArray = Json::array(); for (auto &matrix: Matrixes) { jsonArray.push_back(matrix); } - dRenderGroup0["Matrixes"] = jsonArray; + RenderGroup0["Matrixes"] = jsonArray; } } } @@ -761,6 +788,7 @@ struct RenderGroup : zeno::INode { ZENDEFNODE( RenderGroup, { { + {"string", "RenderGroupID"}, {"list", "items"}, {"bool", "static", "1"}, {"string", "Matrixes", "Identity"}, diff --git a/zeno/tpls/include/endianness.h b/zeno/tpls/include/endianness.h deleted file mode 100644 index 5a80e1d25f..0000000000 --- a/zeno/tpls/include/endianness.h +++ /dev/null @@ -1,157 +0,0 @@ -#pragma once - -#if defined(__GLIBC__) || defined(__GNU_LIBRARY__) || defined(__ANDROID__) - #include -#elif defined(__APPLE__) && defined(__MACH__) - #include -#elif defined(BSD) || defined(_SYSTYPE_BSD) - #if defined(__OpenBSD__) - #include - #else - #include - #endif -#endif - -#if defined(__BYTE_ORDER) - #if defined(__BIG_ENDIAN) && (__BYTE_ORDER == __BIG_ENDIAN) - #define BIGENDIAN - #elif defined(__LITTLE_ENDIAN) && (__BYTE_ORDER == __LITTLE_ENDIAN) - #define LITTLEENDIAN - #endif -#elif defined(_BYTE_ORDER) - #if defined(_BIG_ENDIAN) && (_BYTE_ORDER == _BIG_ENDIAN) - #define BIGENDIAN - #elif defined(_LITTLE_ENDIAN) && (_BYTE_ORDER == _LITTLE_ENDIAN) - #define LITTLEENDIAN - #endif -#elif defined(__BIG_ENDIAN__) - #define BIGENDIAN -#elif defined(__LITTLE_ENDIAN__) - #define LITTLEENDIAN -#else - #if defined(__ARMEL__) || \ - defined(__THUMBEL__) || \ - defined(__AARCH64EL__) || \ - defined(_MIPSEL) || \ - defined(__MIPSEL) || \ - defined(__MIPSEL__) || \ - defined(__ia64__) || defined(_IA64) || \ - defined(__IA64__) || defined(__ia64) || \ - defined(_M_IA64) || defined(__itanium__) || \ - defined(i386) || defined(__i386__) || \ - defined(__i486__) || defined(__i586__) || \ - defined(__i686__) || defined(__i386) || \ - defined(_M_IX86) || defined(_X86_) || \ - defined(__THW_INTEL__) || defined(__I86__) || \ - defined(__INTEL__) || \ - defined(__x86_64) || defined(__x86_64__) || \ - defined(__amd64__) || defined(__amd64) || \ - defined(_M_X64) || \ - defined(__bfin__) || defined(__BFIN__) || \ - defined(bfin) || defined(BFIN) - - #define LITTLEENDIAN - #elif defined(__m68k__) || defined(M68000) || \ - defined(__hppa__) || defined(__hppa) || defined(__HPPA__) || \ - defined(__sparc__) || defined(__sparc) || \ - defined(__370__) || defined(__THW_370__) || \ - defined(__s390__) || defined(__s390x__) || \ - defined(__SYSC_ZARCH__) - - #define BIGENDIAN - - #elif defined(__arm__) || defined(__arm64) || defined(__thumb__) || \ - defined(__TARGET_ARCH_ARM) || defined(__TARGET_ARCH_THUMB) || \ - defined(__ARM_ARCH) || \ - defined(_M_ARM) || defined(_M_ARM64) - - #if defined(_WIN32) || defined(_WIN64) || \ - defined(__WIN32__) || defined(__TOS_WIN__) || \ - defined(__WINDOWS__) - - #define LITTLEENDIAN - - #else - #error "Cannot determine system endianness." - #endif - #endif -#endif - - -#if defined(BIGENDIAN) - // Try to use compiler intrinsics - #if defined(__INTEL_COMPILER) || defined(__ICC) - #define betole16(x) _bswap16(x) - #define betole32(x) _bswap(x) - #define betole64(x) _bswap64(x) - #elif defined(__GNUC__) // GCC and CLANG - #define betole16(x) __builtin_bswap16(x) - #define betole32(x) __builtin_bswap32(x) - #define betole64(x) __builtin_bswap64(x) - #elif defined(_MSC_VER) // MSVC - #include - #define betole16(x) _byteswap_ushort(x) - #define betole32(x) _byteswap_ulong(x) - #define betole64(x) _byteswap_uint64(x) - #else - #define FALLBACK_SWAP - #define betole16(x) swap_u16(x) - #define betole32(x) swap_u32(x) - #define betole64(x) swap_u64(x) - #endif - #define betole128(x) swap_u128(x) - #define betole256(x) swap_u256(x) -#else - #define betole16(x) (x) - #define betole32(x) (x) - #define betole64(x) (x) - #define betole128(x) (x) - #define betole256(x) (x) -#endif // BIGENDIAN - -#if defined(BIGENDIAN) - #include - #include - #include - #include - - inline __m128i swap_u128(__m128i value) { - const __m128i shuffle = _mm_set_epi64x(0x0001020304050607, 0x08090a0b0c0d0e0f); - return _mm_shuffle_epi8(value, shuffle); - } - - inline __m256i swap_u256(__m256i value) { - const __m256i shuffle = _mm256_set_epi64x(0x0001020304050607, 0x08090a0b0c0d0e0f, 0x0001020304050607, 0x08090a0b0c0d0e0f); - return _mm256_shuffle_epi8(value, shuffle); - } -#endif // BIGENDIAN - -#if defined(FALLBACK_SWAP) - #include - inline uint16_t swap_u16(uint16_t value) - { - return - ((value & 0xFF00u) >> 8u) | - ((value & 0x00FFu) << 8u); - } - inline uint32_t swap_u32(uint32_t value) - { - return - ((value & 0xFF000000u) >> 24u) | - ((value & 0x00FF0000u) >> 8u) | - ((value & 0x0000FF00u) << 8u) | - ((value & 0x000000FFu) << 24u); - } - inline uint64_t swap_u64(uint64_t value) - { - return - ((value & 0xFF00000000000000u) >> 56u) | - ((value & 0x00FF000000000000u) >> 40u) | - ((value & 0x0000FF0000000000u) >> 24u) | - ((value & 0x000000FF00000000u) >> 8u) | - ((value & 0x00000000FF000000u) << 8u) | - ((value & 0x0000000000FF0000u) << 24u) | - ((value & 0x000000000000FF00u) << 40u) | - ((value & 0x00000000000000FFu) << 56u); - } -#endif // FALLBACK_SWAP diff --git a/zeno/tpls/include/uuid_v4.h b/zeno/tpls/include/uuid_v4.h deleted file mode 100644 index ed444984aa..0000000000 --- a/zeno/tpls/include/uuid_v4.h +++ /dev/null @@ -1,276 +0,0 @@ -/* -MIT License - -Copyright (c) 2018 Xavier "Crashoz" Launey -*/ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "endianness.h" - -namespace UUIDv4 { - -/* - Converts a 128-bits unsigned int to an UUIDv4 string representation. - Uses SIMD via Intel's AVX2 instruction set. - */ -void inline m128itos(__m128i x, char* mem) { - // Expand each byte in x to two bytes in res - // i.e. 0x12345678 -> 0x0102030405060708 - // Then translate each byte to its hex ascii representation - // i.e. 0x0102030405060708 -> 0x3132333435363738 - const __m256i mask = _mm256_set1_epi8(0x0F); - const __m256i add = _mm256_set1_epi8(0x06); - const __m256i alpha_mask = _mm256_set1_epi8(0x10); - const __m256i alpha_offset = _mm256_set1_epi8(0x57); - - __m256i a = _mm256_castsi128_si256(x); - __m256i as = _mm256_srli_epi64(a, 4); - __m256i lo = _mm256_unpacklo_epi8(as, a); - __m128i hi = _mm256_castsi256_si128(_mm256_unpackhi_epi8(as, a)); - __m256i c = _mm256_inserti128_si256(lo, hi, 1); - __m256i d = _mm256_and_si256(c, mask); - __m256i alpha = _mm256_slli_epi64(_mm256_and_si256(_mm256_add_epi8(d, add), alpha_mask), 3); - __m256i offset = _mm256_blendv_epi8(_mm256_slli_epi64(add, 3), alpha_offset, alpha); - __m256i res = _mm256_add_epi8(d, offset); - - // Add dashes between blocks as specified in RFC-4122 - // 8-4-4-4-12 - const __m256i dash_shuffle = _mm256_set_epi32(0x0b0a0908, 0x07060504, 0x80030201, 0x00808080, 0x0d0c800b, 0x0a090880, 0x07060504, 0x03020100); - const __m256i dash = _mm256_set_epi64x(0x0000000000000000ull, 0x2d000000002d0000ull, 0x00002d000000002d, 0x0000000000000000ull); - - __m256i resd = _mm256_shuffle_epi8(res, dash_shuffle); - resd = _mm256_or_si256(resd, dash); - - _mm256_storeu_si256((__m256i*)mem, betole256(resd)); - *(uint16_t*)(mem+16) = betole16(_mm256_extract_epi16(res, 7)); - *(uint32_t*)(mem+32) = betole32(_mm256_extract_epi32(res, 7)); -} - -/* - Converts an UUIDv4 string representation to a 128-bits unsigned int. - Uses SIMD via Intel's AVX2 instruction set. - */ -__m128i inline stom128i(const char* mem) { - // Remove dashes and pack hex ascii bytes in a 256-bits int - const __m256i dash_shuffle = _mm256_set_epi32(0x80808080, 0x0f0e0d0c, 0x0b0a0908, 0x06050403, 0x80800f0e, 0x0c0b0a09, 0x07060504, 0x03020100); - - __m256i x = betole256(_mm256_loadu_si256((__m256i*)mem)); - x = _mm256_shuffle_epi8(x, dash_shuffle); - x = _mm256_insert_epi16(x, betole16(*(uint16_t*)(mem+16)), 7); - x = _mm256_insert_epi32(x, betole32(*(uint32_t*)(mem+32)), 7); - - // Build a mask to apply a different offset to alphas and digits - const __m256i sub = _mm256_set1_epi8(0x2F); - const __m256i mask = _mm256_set1_epi8(0x20); - const __m256i alpha_offset = _mm256_set1_epi8(0x28); - const __m256i digits_offset = _mm256_set1_epi8(0x01); - const __m256i unweave = _mm256_set_epi32(0x0f0d0b09, 0x0e0c0a08, 0x07050301, 0x06040200, 0x0f0d0b09, 0x0e0c0a08, 0x07050301, 0x06040200); - const __m256i shift = _mm256_set_epi32(0x00000000, 0x00000004, 0x00000000, 0x00000004, 0x00000000, 0x00000004, 0x00000000, 0x00000004); - - // Translate ascii bytes to their value - // i.e. 0x3132333435363738 -> 0x0102030405060708 - // Shift hi-digits - // i.e. 0x0102030405060708 -> 0x1002300450067008 - // Horizontal add - // i.e. 0x1002300450067008 -> 0x12345678 - __m256i a = _mm256_sub_epi8(x, sub); - __m256i alpha = _mm256_slli_epi64(_mm256_and_si256(a, mask), 2); - __m256i sub_mask = _mm256_blendv_epi8(digits_offset, alpha_offset, alpha); - a = _mm256_sub_epi8(a, sub_mask); - a = _mm256_shuffle_epi8(a, unweave); - a = _mm256_sllv_epi32(a, shift); - a = _mm256_hadd_epi32(a, _mm256_setzero_si256()); - a = _mm256_permute4x64_epi64(a, 0b00001000); - - return _mm256_castsi256_si128(a); -} - -/* - * UUIDv4 (random 128-bits) RFC-4122 - */ -class UUID { - public: - UUID() - {} - - UUID(const UUID &other) { - __m128i x = _mm_load_si128((__m128i*)other.data); - _mm_store_si128((__m128i*)data, x); - } - - /* Builds a 128-bits UUID */ - UUID(__m128i uuid) { - _mm_store_si128((__m128i*)data, uuid); - } - - UUID(uint64_t x, uint64_t y) { - __m128i z = _mm_set_epi64x(x, y); - _mm_store_si128((__m128i*)data, z); - } - - UUID(const uint8_t* bytes) { - __m128i x = _mm_loadu_si128((__m128i*)bytes); - _mm_store_si128((__m128i*)data, x); - } - - /* Builds an UUID from a byte string (16 bytes long) */ - explicit UUID(const std::string &bytes) { - __m128i x = betole128(_mm_loadu_si128((__m128i*)bytes.data())); - _mm_store_si128((__m128i*)data, x); - } - - /* Static factory to parse an UUID from its string representation */ - static UUID fromStrFactory(const std::string &s) { - return fromStrFactory(s.c_str()); - } - - static UUID fromStrFactory(const char* raw) { - return UUID(stom128i(raw)); - } - - void fromStr(const char* raw) { - _mm_store_si128((__m128i*)data, stom128i(raw)); - } - - UUID& operator=(const UUID &other) { - if (&other == this) { - return *this; - } - __m128i x = _mm_load_si128((__m128i*)other.data); - _mm_store_si128((__m128i*)data, x); - return *this; - } - - friend bool operator==(const UUID &lhs, const UUID &rhs) { - __m128i x = _mm_load_si128((__m128i*)lhs.data); - __m128i y = _mm_load_si128((__m128i*)rhs.data); - - __m128i neq = _mm_xor_si128(x, y); - return _mm_test_all_zeros(neq, neq); - } - - friend bool operator<(const UUID &lhs, const UUID &rhs) { - // There are no trivial 128-bits comparisons in SSE/AVX - // It's faster to compare two uint64_t - uint64_t *x = (uint64_t*)lhs.data; - uint64_t *y = (uint64_t*)rhs.data; - return *x < *y || (*x == *y && *(x + 1) < *(y + 1)); - } - - friend bool operator!=(const UUID &lhs, const UUID &rhs) { return !(lhs == rhs); } - friend bool operator> (const UUID &lhs, const UUID &rhs) { return rhs < lhs; } - friend bool operator<=(const UUID &lhs, const UUID &rhs) { return !(lhs > rhs); } - friend bool operator>=(const UUID &lhs, const UUID &rhs) { return !(lhs < rhs); } - - /* Serializes the uuid to a byte string (16 bytes) */ - std::string bytes() const { - std::string mem; - bytes(mem); - return mem; - } - - void bytes(std::string &out) const { - out.resize(sizeof(data)); - bytes((char*)out.data()); - } - - void bytes(char* bytes) const { - __m128i x = betole128(_mm_load_si128((__m128i*)data)); - _mm_storeu_si128((__m128i*)bytes, x); - } - - /* Converts the uuid to its string representation */ - std::string str() const { - std::string mem; - str(mem); - return mem; - } - - void str(std::string &s) const { - s.resize(36); - str((char*)s.data()); - } - - void str(char *res) const { - __m128i x = _mm_load_si128((__m128i*)data); - m128itos(x, res); - } - - friend std::ostream& operator<< (std::ostream& stream, const UUID& uuid) { - return stream << uuid.str(); - } - - friend std::istream& operator>> (std::istream& stream, UUID& uuid) { - std::string s; - stream >> s; - uuid = fromStrFactory(s); - return stream; - } - - size_t hash() const { - const uint64_t a = *((uint64_t*)data); - const uint64_t b = *((uint64_t*)&data[8]); - return a ^ (b + 0x9e3779b9 + (a << 6) + (a >> 2)); - } - - private: - alignas(128) uint8_t data[16]; -}; - -/* - Generates UUIDv4 from a provided random generator (c++11 module) - std::mt19937_64 is highly recommended as it has a SIMD implementation that - makes it very fast and it produces high quality randomness. - */ -template -class UUIDGenerator { - public: - UUIDGenerator() : generator(new RNG(std::random_device()())), distribution(std::numeric_limits::min(), std::numeric_limits::max()) - {} - - UUIDGenerator(uint64_t seed) : generator(new RNG(seed)), distribution(std::numeric_limits::min(), std::numeric_limits::max()) - {} - - UUIDGenerator(RNG &gen) : generator(gen), distribution(std::numeric_limits::min(), std::numeric_limits::max()) - {} - - /* Generates a new UUID */ - UUID getUUID() { - // The two masks set the uuid version (4) and variant (1) - const __m128i and_mask = _mm_set_epi64x(0xFFFFFFFFFFFFFF3Full, 0xFF0FFFFFFFFFFFFFull); - const __m128i or_mask = _mm_set_epi64x(0x0000000000000080ull, 0x0040000000000000ull); - __m128i n = _mm_set_epi64x(distribution(*generator), distribution(*generator)); - __m128i uuid = _mm_or_si128(_mm_and_si128(n, and_mask), or_mask); - - return UUID(uuid); - } - - private: - std::shared_ptr generator; - std::uniform_int_distribution distribution; -}; - -} - -namespace std { - template <> struct hash - { - size_t operator()(const UUIDv4::UUID & uuid) const - { - return uuid.hash(); - } - }; -} From d90524c36f95ee36b8fd50e89fdf9562929d4768 Mon Sep 17 00:00:00 2001 From: zhouhang95 <765229842@qq.com> Date: Fri, 1 Nov 2024 15:13:36 +0800 Subject: [PATCH 5/7] WIP --- zeno/src/nodes/JsonProcess.cpp | 70 +++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 2 deletions(-) diff --git a/zeno/src/nodes/JsonProcess.cpp b/zeno/src/nodes/JsonProcess.cpp index e81e2f7ee1..8009d42e13 100644 --- a/zeno/src/nodes/JsonProcess.cpp +++ b/zeno/src/nodes/JsonProcess.cpp @@ -12,7 +12,7 @@ #include #include -using Json = nlohmann::json; +using Json = nlohmann::ordered_json; namespace zeno { struct JsonObject : IObjectClone { @@ -678,11 +678,12 @@ struct CreateRenderInstance : zeno::INode { } auto out_json = std::make_shared(); - out_json->json["BasicRenderInstance"][instID] = { + out_json->json["BasicRenderInstances"][instID] = { {"Geom", Geom}, {"Matrix", Matrix}, {"Material", Material}, }; + out_json->json["Root"] = instID; set_output("json", out_json); } }; @@ -802,4 +803,69 @@ ZENDEFNODE( RenderGroup, { }, }); +struct RenderGroup2 : zeno::INode { + virtual void apply() override { + auto RenderGroupID = get_input2("RenderGroupID"); + auto is_static = get_input2("static"); + auto Matrix_string = get_input2("Matrixes"); + std::vector Matrixes = zeno::split_str(Matrix_string, {' ', '\n'}); + auto items = get_input("items")->get(); + + Json node = {}; + node["Objects"] = Json::array(); + for (const auto& item: items) { + node["Objects"].push_back(item->json["Root"]); + } + node["Matrixes"] = Json::array(); + for (auto &matrix: Matrixes) { + node["Matrixes"].push_back(matrix); + } + + auto out_json = std::make_shared(); + out_json->json["Root"] = RenderGroupID; + + for (const auto& item: items) { + for (auto& [key, value] : item->json["BasicRenderInstances"].items()) { + out_json->json["BasicRenderInstances"][key] = value; + } + for (auto& [key, value] : item->json["DynamicRenderGroups"].items()) { + out_json->json["DynamicRenderGroups"][key] = value; + } + for (auto& [key, value] : item->json["StaticRenderGroups"].items()) { + if (is_static) { + out_json->json["StaticRenderGroups"][key] = value; + } + else { + out_json->json["DynamicRenderGroups"][key] = value; + } + } + } + + if (is_static) { + out_json->json["StaticRenderGroups"][RenderGroupID] = node; + } + else { + out_json->json["DynamicRenderGroups"][RenderGroupID] = node; + } + + set_output("json", out_json); + } +}; + +ZENDEFNODE( RenderGroup2, { + { + {"string", "RenderGroupID"}, + {"list", "items"}, + {"bool", "static", "1"}, + {"string", "Matrixes", "Identity"}, + }, + { + {"json"}, + }, + {}, + { + "shader", + }, +}); + } \ No newline at end of file From 5129f660ebf965358f00c5c3a0e6fec6fb8d07c0 Mon Sep 17 00:00:00 2001 From: zhouhang95 <765229842@qq.com> Date: Fri, 1 Nov 2024 19:55:32 +0800 Subject: [PATCH 6/7] WIP --- zeno/src/nodes/JsonProcess.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeno/src/nodes/JsonProcess.cpp b/zeno/src/nodes/JsonProcess.cpp index 8009d42e13..551b2309a4 100644 --- a/zeno/src/nodes/JsonProcess.cpp +++ b/zeno/src/nodes/JsonProcess.cpp @@ -841,7 +841,7 @@ struct RenderGroup2 : zeno::INode { } } - if (is_static) { + if (is_static && !out_json->json.contains("DynamicRenderGroups")) { out_json->json["StaticRenderGroups"][RenderGroupID] = node; } else { From 34971576b3f5be1c2a7ae14675086ad22e6df5a4 Mon Sep 17 00:00:00 2001 From: zhouhang95 <765229842@qq.com> Date: Fri, 1 Nov 2024 20:10:32 +0800 Subject: [PATCH 7/7] OK --- zeno/src/nodes/JsonProcess.cpp | 121 ++++++--------------------------- 1 file changed, 21 insertions(+), 100 deletions(-) diff --git a/zeno/src/nodes/JsonProcess.cpp b/zeno/src/nodes/JsonProcess.cpp index 551b2309a4..d9a5bf9d66 100644 --- a/zeno/src/nodes/JsonProcess.cpp +++ b/zeno/src/nodes/JsonProcess.cpp @@ -703,113 +703,17 @@ ZENDEFNODE( CreateRenderInstance, { "shader", }, }); + struct RenderGroup : zeno::INode { virtual void apply() override { auto RenderGroupID = get_input2("RenderGroupID"); auto is_static = get_input2("static"); auto Matrix_string = get_input2("Matrixes"); std::vector Matrixes = zeno::split_str(Matrix_string, {' ', '\n'}); - auto items = get_input("items")->get(); - // Check group id not duplicated - { - if (RenderGroupID.empty()) { - auto info = zeno::format("RenderGroupID {} can not be empty!", RenderGroupID); - throw zeno::makeError(info); - } - for (const auto& item: items) { - if (item->json.contains("BasicRenderInstance")) { - for (auto& [key, _] : item->json["BasicRenderInstance"].items()) { - if (key == RenderGroupID) { - auto info = zeno::format("RenderGroupID {} can not be duplicated!", RenderGroupID); - throw zeno::makeError(info); - } - } - } - if (item->json.contains("BasicRenderInstances")) { - for (auto& [key, _] : item->json["BasicRenderInstances"].items()) { - if (key == RenderGroupID) { - auto info = zeno::format("RenderGroupID {} can not be duplicated!", RenderGroupID); - throw zeno::makeError(info); - } - } - } - if (item->json.contains("StaticRenderGroups")) { - for (auto& [key, _] : item->json["StaticRenderGroups"].items()) { - if (key == RenderGroupID) { - auto info = zeno::format("RenderGroupID {} can not be duplicated!", RenderGroupID); - throw zeno::makeError(info); - } - } - } - if (item->json.contains("DynamicRenderGroups")) { - for (auto& [key, _] : item->json["DynamicRenderGroups"].items()) { - if (key == RenderGroupID) { - auto info = zeno::format("RenderGroupID {} can not be duplicated!", RenderGroupID); - throw zeno::makeError(info); - } - } - } - } - } - - auto out_json = std::make_shared(); - out_json->json["BasicRenderInstances"] = {}; - auto &bris = out_json->json["BasicRenderInstances"]; - - for (const auto& item: items) { - if (item->json.contains("BasicRenderInstance")) { - for (auto& [key, value] : item->json["BasicRenderInstance"].items()) { - if (bris.contains(key)) { - auto log = zeno::format("Error: Instance {} already exists", key); - log_error(log); - throw zeno::makeError(log); - } - bris[key] = value; - auto category = is_static ? "StaticRenderGroups" : "DynamicRenderGroups"; - auto & RenderGroup0 = out_json->json[category][RenderGroupID]; - if (RenderGroup0.contains("Objects") == false) { - RenderGroup0["Objects"] = Json::array(); - } - RenderGroup0["Objects"].push_back(key); - if (RenderGroup0.contains("Matrixes") == false) { - Json jsonArray = Json::array(); - for (auto &matrix: Matrixes) { - jsonArray.push_back(matrix); - } - RenderGroup0["Matrixes"] = jsonArray; - } - } - } - } - - set_output("json", out_json); - } -}; - -ZENDEFNODE( RenderGroup, { - { - {"string", "RenderGroupID"}, - {"list", "items"}, - {"bool", "static", "1"}, - {"string", "Matrixes", "Identity"}, - }, - { - {"json"}, - }, - {}, - { - "shader", - }, -}); -struct RenderGroup2 : zeno::INode { - virtual void apply() override { - auto RenderGroupID = get_input2("RenderGroupID"); - auto is_static = get_input2("static"); - auto Matrix_string = get_input2("Matrixes"); - std::vector Matrixes = zeno::split_str(Matrix_string, {' ', '\n'}); - auto items = get_input("items")->get(); + std::set rinst; + std::map id_checker; Json node = {}; node["Objects"] = Json::array(); @@ -827,9 +731,11 @@ struct RenderGroup2 : zeno::INode { for (const auto& item: items) { for (auto& [key, value] : item->json["BasicRenderInstances"].items()) { out_json->json["BasicRenderInstances"][key] = value; + rinst.insert(key); } for (auto& [key, value] : item->json["DynamicRenderGroups"].items()) { out_json->json["DynamicRenderGroups"][key] = value; + id_checker[key] += 1; } for (auto& [key, value] : item->json["StaticRenderGroups"].items()) { if (is_static) { @@ -838,6 +744,7 @@ struct RenderGroup2 : zeno::INode { else { out_json->json["DynamicRenderGroups"][key] = value; } + id_checker[key] += 1; } } @@ -847,12 +754,26 @@ struct RenderGroup2 : zeno::INode { else { out_json->json["DynamicRenderGroups"][RenderGroupID] = node; } + id_checker[RenderGroupID] += 1; + + for (auto const &[GroupID, count]: id_checker) { + if (count > 1) { + auto info = zeno::format("Group ID {} is not unique!", GroupID); + zeno::log_error(info); + throw zeno::makeError(info); + } + if (rinst.count(GroupID)) { + auto info = zeno::format("Group ID {} is not same with RenderInstance ID!", GroupID); + zeno::log_error(info); + throw zeno::makeError(info); + } + } set_output("json", out_json); } }; -ZENDEFNODE( RenderGroup2, { +ZENDEFNODE( RenderGroup, { { {"string", "RenderGroupID"}, {"list", "items"},