From 15740faf9fe9fe4be08965098bbf2947e096aeeb Mon Sep 17 00:00:00 2001 From: chai Date: Wed, 14 Aug 2019 22:50:43 +0800 Subject: +Unity Runtime code --- Runtime/Filters/Mesh/VertexData.cpp | 559 ++++++++++++++++++++++++++++++++++++ 1 file changed, 559 insertions(+) create mode 100644 Runtime/Filters/Mesh/VertexData.cpp (limited to 'Runtime/Filters/Mesh/VertexData.cpp') diff --git a/Runtime/Filters/Mesh/VertexData.cpp b/Runtime/Filters/Mesh/VertexData.cpp new file mode 100644 index 0000000..b922805 --- /dev/null +++ b/Runtime/Filters/Mesh/VertexData.cpp @@ -0,0 +1,559 @@ +#include "UnityPrefix.h" +#include "Configuration/UnityConfigure.h" +#include "VertexData.h" +#include "Runtime/Shaders/VBO.h" +#include "Runtime/Serialize/TransferFunctions/SerializeTransfer.h" +#include "Runtime/Serialize/TransferUtility.h" +#include "Runtime/Serialize/SwapEndianArray.h" +#include + +/* + On most platforms, for skinning/non-uniform-scaling of meshes you would want to split your data into + a hot data stream (position, normal and tangent) and a cold data stream (diffuse and uvs) in order to maximize CPU cache access patterns and + reduce bandwidth and computation ( you won't need to copy the cold data ) +*/ + +VertexStreamsLayout VertexDataInfo::kVertexStreamsDefault = {{ kShaderChannelsAll, 0, 0, 0 }}; +#if UNITY_PS3 + VertexStreamsLayout VertexDataInfo::kVertexStreamsSkinnedHotColdSplit = {{ VERTEX_FORMAT1(Vertex), VERTEX_FORMAT1(Normal), VERTEX_FORMAT1(Tangent), kShaderChannelsCold }}; +#else + VertexStreamsLayout VertexDataInfo::kVertexStreamsSkinnedHotColdSplit = {{ kShaderChannelsHot, kShaderChannelsCold, 0, 0 }}; +# if UNITY_EDITOR + VertexStreamsLayout VertexDataInfo::kVertexStreamsSkinnedHotColdSplitPS3 = {{ VERTEX_FORMAT1(Vertex), VERTEX_FORMAT1(Normal), VERTEX_FORMAT1(Tangent), kShaderChannelsCold }}; +# endif +#endif + +#define MAKE_CHANNEL(fmt, dim) VertexChannelsLayout::Channel(kChannelFormat##fmt, dim) +VertexChannelsLayout VertexDataInfo::kVertexChannelsDefault = +{{ // Array wrapped by struct requires double braces + MAKE_CHANNEL(Float, 3), // position + MAKE_CHANNEL(Float, 3), // normal + MAKE_CHANNEL(Color, 1), // color + MAKE_CHANNEL(Float, 2), // texcoord0 + MAKE_CHANNEL(Float, 2), // texcoord1 + MAKE_CHANNEL(Float, 4) // tangent +}}; +VertexChannelsLayout VertexDataInfo::kVertexChannelsCompressed = +{{ // Array wrapped by struct requires double braces + MAKE_CHANNEL(Float, 3), // position + MAKE_CHANNEL(Float16, 4), // normal + MAKE_CHANNEL(Color, 1), // color + MAKE_CHANNEL(Float16, 2), // texcoord0 + MAKE_CHANNEL(Float16, 2), // texcoord1 + MAKE_CHANNEL(Float16, 4) // tangent +}}; +VertexChannelsLayout VertexDataInfo::kVertexChannelsCompressedAggressive = +{{ // Array wrapped by struct requires double braces + MAKE_CHANNEL(Float, 3), // position + MAKE_CHANNEL(Byte, 4), // normal + MAKE_CHANNEL(Color, 1), // color + MAKE_CHANNEL(Float16, 2), // texcoord0 + MAKE_CHANNEL(Float16, 2), // texcoord1 + MAKE_CHANNEL(Byte, 4) // tangent +}}; +#undef MAKE_CHANNEL + +static const UInt8 kVertexChannelFormatSizes[kChannelFormatCount] = { + 4, // kChannelFormatFloat + 2, // kChannelFormatFloat16 + 4, // kChannelFormatColor + 1 // kChannelFormatByte +}; + +size_t GetChannelFormatSize(UInt8 format) +{ + Assert (format < kChannelFormatCount); + return kVertexChannelFormatSizes[format]; +} + +static bool operator == (const VertexStreamsLayout& lhs, const VertexStreamsLayout& rhs) +{ + return CompareArrays(lhs.channelMasks, rhs.channelMasks, kMaxVertexStreams); +} + +template +void VertexData::Transfer (TransferFunction& transfer) +{ + #if SUPPORT_SERIALIZED_TYPETREES + if (transfer.GetFlags() & kWorkaround35MeshSerializationFuckup) + { + TransferWorkaround35SerializationFuckup (transfer); + return; + } + #endif + + transfer.Transfer (m_CurrentChannels, "m_CurrentChannels", kHideInEditorMask); + transfer.Transfer (m_VertexCount, "m_VertexCount", kHideInEditorMask); + + dynamic_array channels; + dynamic_array streams; + if (transfer.IsWriting ()) + { + channels.resize_uninitialized (kShaderChannelCount); + streams.resize_uninitialized (kMaxVertexStreams); + std::copy (m_Channels, m_Channels + kShaderChannelCount, channels.begin ()); + std::copy (m_Streams, m_Streams + kMaxVertexStreams, streams.begin ()); + } + transfer.Transfer (channels, "m_Channels", kHideInEditorMask); + transfer.Transfer (streams, "m_Streams", kHideInEditorMask); + + if (transfer.IsReading ()) + { + // For compatibility do this even if channels/streams info didn't exist (case 558604) + // In the past there was only a channels mask, UpdateStreams() generates the info from that + if (channels.size () == kShaderChannelCount) + std::copy (channels.begin (), channels.begin () + kShaderChannelCount, m_Channels); + if (streams.size () == kMaxVertexStreams) + std::copy (streams.begin (), streams.begin () + kMaxVertexStreams, m_Streams); + else + std::fill (m_Streams, m_Streams + kMaxVertexStreams, StreamInfo()); + + UInt32 channelsInStreams = 0; + for (int i = 0; i < kMaxVertexStreams ; i++) + channelsInStreams |= m_Streams[i].channelMask; + if (channelsInStreams) + UpdateStreams(channelsInStreams, m_VertexCount, GetStreamsLayout (), GetChannelsLayout ()); + else + UpdateStreams(m_CurrentChannels, m_VertexCount, kVertexStreamsDefault, kVertexChannelsDefault); + } + + transfer.TransferTypeless (&m_DataSize, "m_DataSize", kHideInEditorMask); + if (transfer.DidReadLastProperty ()) + { + if (m_Data) + UNITY_FREE (kMemVertexData, m_Data); + m_Data = (UInt8*)UNITY_MALLOC_ALIGNED (kMemVertexData, VertexData::GetAllocateDataSize (m_DataSize), kVertexDataAlign); + } + + transfer.TransferTypelessData (m_DataSize, m_Data); +} + +#if SUPPORT_SERIALIZED_TYPETREES +template +void VertexData::TransferWorkaround35SerializationFuckup (TransferFunction& transfer) +{ + UInt32 currentChannels = m_CurrentChannels; + transfer.Transfer (currentChannels, "m_CurrentChannels", kHideInEditorMask); + transfer.Transfer (m_VertexCount, "m_VertexCount", kHideInEditorMask); + + TRANSFER(m_Streams[0]); + TRANSFER(m_Streams[1]); + TRANSFER(m_Streams[2]); + TRANSFER(m_Streams[3]); + + if (transfer.IsReading ()) + { + if(m_VertexCount && (currentChannels == 0)) + { + for(int i=0;i(srcPtr)[comp], reinterpret_cast(dstPtr)[comp]); + for ( ; comp < dstDim; comp++) + reinterpret_cast(dstPtr)[comp] = 0.0f; + srcPtr += srcStride; + dstPtr += dstStride; + } + } + else if (srcType == kChannelFormatByte && dstType == kChannelFormatFloat) + { + // decompressing + for (size_t i = 0; i < vertexCount; i++) + { + UInt8 comp = 0; + for ( ; comp < minDim; comp++) + reinterpret_cast(dstPtr)[comp] = s8_to_f32(reinterpret_cast(srcPtr)[comp]); + for ( ; comp < dstDim; comp++) + reinterpret_cast(dstPtr)[comp] = 0.0f; + srcPtr += srcStride; + dstPtr += dstStride; + } + } +#if UNITY_EDITOR + else if (srcType == kChannelFormatFloat && dstType == kChannelFormatFloat16) + { + // compressing + for (size_t i = 0; i < vertexCount; i++) + { + UInt8 comp = 0; + for ( ; comp < minDim; comp++) + g_FloatToHalf.Convert(reinterpret_cast(srcPtr)[comp], reinterpret_cast(dstPtr)[comp]); + for ( ; comp < dstDim; comp++) + reinterpret_cast(dstPtr)[comp] = 0; + srcPtr += srcStride; + dstPtr += dstStride; + } + } + else if (srcType == kChannelFormatFloat && dstType == kChannelFormatByte) + { + // compressing + for (size_t i = 0; i < vertexCount; i++) + { + UInt8 comp = 0; + for ( ; comp < minDim; comp++) + reinterpret_cast(dstPtr)[comp] = f32_to_s8(reinterpret_cast(srcPtr)[comp]); + for ( ; comp < dstDim; comp++) + reinterpret_cast(dstPtr)[comp] = 0; + srcPtr += srcStride; + dstPtr += dstStride; + } + } +#endif + else + ErrorString("Unsupported conversion of vertex formats"); +} + +static void CopyChannels (size_t vertexCount, unsigned copyChannels, + const StreamInfoArray srcStreams, const ChannelInfoArray srcChannels, const UInt8* srcData, + const StreamInfoArray dstStreams, const ChannelInfoArray dstChannels, UInt8* dstData) +{ + for (unsigned chan = copyChannels, i = 0; chan && (i < kShaderChannelCount); i++, chan >>= 1) + { + if (0 == (chan & 1)) + continue; + + const ChannelInfo& srcChannel = srcChannels[i]; + const ChannelInfo& dstChannel = dstChannels[i]; + + const UInt8* srcPtr = srcData + srcChannel.CalcOffset(srcStreams); + UInt8* dstPtr = dstData + dstChannel.CalcOffset(dstStreams); + UInt8 srcStride = srcChannel.CalcStride(srcStreams); + UInt8 dstStride = dstChannel.CalcStride(dstStreams); + + if(srcChannel.format == dstChannel.format) + { + size_t copySize = srcChannel.dimension * GetChannelFormatSize(srcChannel.format); + switch (copySize) + { + case 4: + { + for (size_t i=0; i (dstPtr) + 0) = *(reinterpret_cast (srcPtr) + 0); + srcPtr += srcStride; + dstPtr += dstStride; + } + break; + } + case 8: + { + for (size_t i=0; i (dstPtr) + 0) = *(reinterpret_cast (srcPtr) + 0); + *(reinterpret_cast (dstPtr) + 1) = *(reinterpret_cast (srcPtr) + 1); + srcPtr += srcStride; + dstPtr += dstStride; + } + break; + } + case 12: + { + for (size_t i=0; i (dstPtr) + 0) = *(reinterpret_cast (srcPtr) + 0); + *(reinterpret_cast (dstPtr) + 1) = *(reinterpret_cast (srcPtr) + 1); + *(reinterpret_cast (dstPtr) + 2) = *(reinterpret_cast (srcPtr) + 2); + srcPtr += srcStride; + dstPtr += dstStride; + } + break; + } + default: + { + for (size_t i=0; i(srcVertexCount, m_VertexCount); + CopyChannels(toCopyCount, copyChannels, srcStreams, srcChannels, srcData, m_Streams, m_Channels, m_Data); + UNITY_FREE(kMemVertexData, srcData); + } +} + + +void VertexData::SwapEndianess () +{ + unsigned const kChannelSwapMask = VERTEX_FORMAT5(Vertex, Normal, TexCoord0, TexCoord1, Tangent); + for (int s = 0; s < kMaxVertexStreams; s++) + { + if (m_Streams[s].stride) + { + StreamInfo& stream = m_Streams[s]; + size_t stride = stream.stride; + UInt8* dataStart = m_Data + stream.offset; + UInt8* dataEnd = dataStart + stream.stride * m_VertexCount; + UInt32 channelMask = stream.channelMask; + for (UInt8* p = dataStart, *end = dataEnd; p != end; p += stride) + { + // counting from LSb, 1 denotes that a value should be endian-swapped + int localOffset = 0; + for (unsigned i=0, chan = channelMask, swap = kChannelSwapMask; i>= 1, swap >>= 1) + { + if (chan & 1) + { + size_t componentCount = m_Channels[i].dimension; + size_t componentSize = GetChannelFormatSize(m_Channels[i].format); + if(swap & 1) + { + Assert (m_Channels [i].IsValid()); + SwapEndianArray (p + localOffset, componentSize, componentCount); + } + localOffset += componentCount * componentSize; + } + } + } + } + } +} + +void swap (VertexData& a, VertexData& b) +{ + std::swap_ranges (a.m_Channels, a.m_Channels + kShaderChannelCount, b.m_Channels); + std::swap_ranges (a.m_Streams, a.m_Streams + kMaxVertexStreams, b.m_Streams); + std::swap (a.m_CurrentChannels, b.m_CurrentChannels); + std::swap (a.m_VertexSize, b.m_VertexSize); + std::swap (a.m_VertexCount, b.m_VertexCount); + std::swap (a.m_DataSize, b.m_DataSize); + std::swap (a.m_Data, b.m_Data); +} + +void CopyVertexDataChannels (size_t vertexCount, unsigned copyChannels, const VertexData& srcData, VertexData& dstData) +{ + Assert (vertexCount <= srcData.GetVertexCount() && vertexCount <= dstData.GetVertexCount()); + Assert ((srcData.GetChannelMask() & copyChannels) == copyChannels); + Assert ((dstData.GetChannelMask() & copyChannels) == copyChannels); + CopyChannels (vertexCount, copyChannels, + srcData.GetStreams(), srcData.GetChannels(), srcData.GetDataPtr(), + dstData.GetStreams(), dstData.GetChannels(), dstData.GetDataPtr()); +} + -- cgit v1.1-26-g67d0