当前位置: 首页 > news >正文

ag电子游戏网站开发硅胶模具技术支持东莞网站建设

ag电子游戏网站开发,硅胶模具技术支持东莞网站建设,涿州吧,抓好门户网站 建设Unity DOTS中的baking#xff08;四#xff09;blob assets blob assets表示不可变的二进制数据#xff0c;在运行时也不会发生更改。由于blob assets是只读的#xff0c;这意味着可以安全地并行访问它们。此外#xff0c;blob assets仅限于使用非托管类型#xff0c;这意… Unity DOTS中的baking四blob assets blob assets表示不可变的二进制数据在运行时也不会发生更改。由于blob assets是只读的这意味着可以安全地并行访问它们。此外blob assets仅限于使用非托管类型这意味着它们与Burst编译器兼容。而且由于它们是非托管类型序列化和反序列化的速度要比其他数据格式快得多。blob assets只能包含值类型除了标准的值类型之外还支持三种特殊的数据类型BlobArray, BlobPtr, BlobString。 在baking中创建一个blob asset的过程可以分为以下若干步骤 创建一个BlobBuilder它在Unity内部分配一些内存调用BlobBuilder.ConstructRoot构造blob asset的根节点把需要的数据填充到上一步骤返回的根节点中调用BlobBuilder.CreateBlobAssetReference创建一个BlobAssetReference。这个API会把blob asset复制到最终位置释放第一步创建的BlobBuilder调用AddBlobAsset将blob asset注册到baker中如果不执行这一步blob asset的引用计数将不会更新也就是说blob asset可能会被意外释放调用AddComponent将BlobAssetReference添加到entity上。 在官网了解完这些理论知识之后我们来动手实践一下。首先定义一个BlobAssetReference引用的struct MyBlobData它包含一个BlobArray和一个int public struct MyBlobData {public BlobArrayint blobArray;public int blobInt; }然后再定义一个component它包含一个BlobAssetReference public struct MyBlobComponent : IComponentData {public BlobAssetReferenceMyBlobData blobReference; }接下来就是根据上面所说的步骤创建出BlobAssetReference public BlobAssetReferenceMyBlobData CreateBlobData() {using (var blobBuilder new BlobBuilder(Allocator.TempJob)){ref var root ref blobBuilder.ConstructRootMyBlobData();var array blobBuilder.Allocate(ref root.blobArray, 10);for (int i 0; i 10; i){array[i] i;}root.blobInt 42;return blobBuilder.CreateBlobAssetReferenceMyBlobData(Allocator.Persistent);} }最后就是把BlobAssetReference注册到baker里去 public override void Bake(MyBlobAssetAuthoring authoring) {var entity GetEntity(TransformUsageFlags.None);var blobReference CreateBlobData();AddBlobAsset(ref blobReference, out _);AddComponent(entity, new MyBlobComponent { blobReference blobReference }); }此时在Unity里可以看到MyBlobComponent但是无法看到component里数据的详细信息 我们可以借助System在运行时打印这个component的信息 foreach (var blob in SystemAPI.QueryRefRWMyBlobComponent()) {int x blob.ValueRO.blobReference.Value.blobArray[4];int y blob.ValueRO.blobReference.Value.blobInt;Debug.Log(string.Format ({0}, {1}, x, y)); }可以看到一切正常。那么我们现在回过头来看看Unity官方文档中创建一个blob asset的过程每一步骤背后究竟做了哪些事情。 第一步创建BlobBuilderBlobBuilder的构造函数会初始化内部使用的若干成员变量 /// summary /// Constructs a BlobBuilder object. /// /summary /// param nameallocatorThe type of allocator to use for the BlobBuilders internal, temporary data. Use /// see crefUnity.Collections.Allocator.Temp/ unless the BlobBuilder exists across more than four Unity frames./param /// param namechunkSize(Optional) The minimum amount of memory to allocate while building an asset. /// The default value should suit most use cases. A smaller chunkSize results in more allocations; a larger /// chunkSize could increase the BlobBuilders total memory allocation (which is freed when you dispose of /// the BlobBuilder./param public BlobBuilder(AllocatorManager.AllocatorHandle allocator, int chunkSize 65536) {m_allocator allocator;m_allocations new NativeListBlobAllocation(16, m_allocator);m_patches new NativeListOffsetPtrPatch(16, m_allocator);m_chunkSize CollectionHelper.Align(chunkSize, 16);m_currentChunkIndex -1; }注释中提到了两个参数的作用allocator用于BlobBuilder内部数据的分配除非BlobBuilder的生命周期很长否则就应该使用Allocator.Temp用完就回收chunkSize用来控制BlobBuilder存放数据的内存块大小太小的话会导致多次内存分配太大则会导致内存占用负担一般用默认值就可以了。 函数体内部初始化了5个成员变量m_allocations是一个BlobAllocation类型的list它记录了每个内存块chunk当前的状态即内存块的起始指针p和当前已经分配掉的内存大小size。 struct BlobAllocation {public int size;public byte* p; }m_patches则是一个OffsetPtrPatch类型的list它记录了需要patch的数据结构内存分配的信息。什么是需要patch的数据结构我们前面提到blob assets除了支持标准值类型之外还支持BlobArray, BlobPtr, BlobString这三种类型。这三种类型的变量在初始化时往往还没有真正地分配所需要的内存后续分配内存时需要通过一种方式把变量和内存关联起来。OffsetPtrPatch类型记录了变量的起始地址指针offsetPtr以及与变量关联的内存分配信息target还有一个length字段记录数组的长度。 struct OffsetPtrPatch {public int* offsetPtr;public BlobDataRef target;public int length; // if length ! 0 this is an array patch and the length should be patched }BlobDataRef类型包含此次内存分配所在的chunk index以及在chunk中的内存偏移量offset struct BlobDataRef {public int allocIndex;public int offset; }m_chunkSize就是存放数据的内存块大小这里会对传入的参数值进行处理返回一个16字节对齐的大小。对齐函数的实现也蛮有趣的 /// summary /// Returns an allocation size in bytes that factors in alignment. /// /summary /// examplecode /// // 55 aligned to 16 is 64. /// int size CollectionHelper.Align(55, 16); /// /code/example /// param namesizeThe size to align./param /// param namealignmentPowerOfTwoA non-zero, positive power of two./param /// returnsThe smallest integer that is greater than or equal to size and is a multiple of alignmentPowerOfTwo./returns /// exception crefArgumentExceptionThrown if alignmentPowerOfTwo is not a non-zero, positive power of two./exception public static int Align(int size, int alignmentPowerOfTwo) {if (alignmentPowerOfTwo 0)return size;CheckIntPositivePowerOfTwo(alignmentPowerOfTwo);return (size alignmentPowerOfTwo - 1) ~(alignmentPowerOfTwo - 1); }首先要检查传入的对齐字节数是不是2的幂 [Conditional(ENABLE_UNITY_COLLECTIONS_CHECKS), Conditional(UNITY_DOTS_DEBUG)] internal static void CheckIntPositivePowerOfTwo(int value) {var valid (value 0) ((value (value - 1)) 0);if (!valid){throw new ArgumentException($Alignment requested: {value} is not a non-zero, positive power of two.);} }2的幂的二进制表示为1000…000减一则为01111…111按位与之后必为0。 所谓的字节对齐就是要找到离传入参数值最接近的字节对齐的倍数。那么我们只需要对原来的size加上alignmentPowerOfTwo - 1就能保证得到的值一定超过了这个最接近的对齐值。接下来只要把超出的部分去掉就可以了对alignmentPowerOfTwo - 1取反得到的就是1111…1000…000后面的这些0就是个mask按位与这个mask就可以去掉超出的部分了。 最后一个成员变量m_currentChunkIndex表示当前已经分配到的chunk index初始化时还没开始内存分配默认为-1。 第二步调用ConstructRoot创建根节点它会分配出足够容纳传入类型T的空间。 /// summary /// Creates the top-level fields of a single blob asset. /// /summary /// remarks /// This function allocates memory for the top-level fields of a blob asset and returns a reference to it. Use /// this root reference to initialize field values and to allocate memory for arrays and structs. /// /remarks /// typeparam nameTA struct that defines the structure of the blob asset./typeparam /// returnsA reference to the blob data under construction./returns public ref T ConstructRootT() where T : struct {var allocation Allocate(UnsafeUtility.SizeOfT(), UnsafeUtility.AlignOfT());return ref UnsafeUtility.AsRefT(AllocationToPointer(allocation)); }UnsafeUtility.SizeOfT()会返回struct的大小这里的大小是带有padding的比如我们这里的struct MyBlobData返回的大小为12。UnsafeUtility.AlignOfT()返回的是struct的对齐字节对于struct MyBlobData对齐字节为4如果MyBlobData中包含一个long成员对齐字节就是8了。 下层的Allocate函数会根据传入的参数size和alignment进行内存分配。函数返回一个BlobDataRef类型的变量表示此次分配的结果即分配到了哪个chunk以及在chunk中的地址。内存分配的策略其实不算复杂我们这里不去分析代码而是使用图示的方式来表达。 首先初始情况下m_currentChunkIndex为-1那么需要直接分配一个chunk然后将m_currentChunkIndex设置为0并保存分配的chunk信息。由于是一个空白的chunk那么就可以从chunk的首地址开始分配。 如图所示p和size表示本次分配之后的chunk信息p为chunk的首地址size为已经分配掉的内存大小allocIndex和offset表示本次分配的结果allocIndex表示分配的内存在第0号chunk上offset表示分配的内存首地址相对于chunk的首地址偏移量这里为0。 有了chunk之后后续的内存分配都在这个chunk上进行。为了保证存取数据的效率后续分配的首地址都在对应struct的对齐字节整数倍上进行。 如图所示第二次分配后chunk的size信息需要更新为两次分配的内存大小以及第二次分配用于字节对齐的大小总和。此次分配的结果offset不再为0而是chunk空闲的首地址再加上用于字节对齐的偏移量。 举个通俗的例子假如第一次分配了12字节的struct内存而第二次要分配的struct总共64字节但它是8字节对齐的那么这里就不会紧挨着从12字节的位置继续分配而是计算8字节对齐的整数倍也就是16字节处开始分配这个struct。这样两个struct之间其实是有4个字节的间隙用于第二个struct字节对齐的。 当chunk剩余的内存空间不足时就会再去申请一个新的chunk同时会把上一个chunk中已经分配的空间调整到16字节对齐这是因为chunk都是按照16字节对齐的地址进行分配的。 那如果需要分配的内存超过一个chunk的大小要怎么办呢Unity会先计算一个16字节对齐后的大小然后直接分配一个这样大的chunk。也就是说Unity内部维护的chunk list每个chunk的大小其实未必相同。 根据Allocate函数返回的分配结果要如何转换成对应T类型的对象呢我们前面提到分配的结果包含了分配的chunk索引以及在chunk中的地址偏移量。那么只需要拿到chunk的首地址加上偏移量就能得到实际分配T类型对象的指针了 void* AllocationToPointer(BlobDataRef blobDataRef) {return m_allocations[blobDataRef.allocIndex].p blobDataRef.offset; }再把指针强转成对象即可。 [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static ref T AsRefT(void* ptr) where T : struct {return ref *(T*)ptr; }第三步我们的Component中还包含了BlobArray那么也需要为它分配内存这里调用的是BlobBuilder.Allocate函数它接受一个BlobArray对象的引用以及要创建的数组大小这两个参数返回一个BlobBuilderArray类对象这个对象封装了数组访问的行为。 /// summary /// Allocates enough memory to store paramref namelength/ elements of struct typeparamref nameT/. /// /summary /// param nameptrA reference to a BlobArray field in a blob asset./param /// param namelengthThe number of elements to allocate./param /// typeparam nameTThe struct data type./typeparam /// returnsA reference to the newly allocated array as a mutable BlobBuilderArray instance./returns public BlobBuilderArrayT AllocateT(ref BlobArrayT ptr, int length) where T : struct {return Allocate(ref ptr, length, UnsafeUtility.AlignOfT()); }数组对象的内存分配逻辑与我们之前说的根节点内存分配逻辑大体相似只不过这里需要额外考虑一点如何把新分配的数组内存与对象本身关联起来。分配数组内存的时机往往是在对象初始化之后。Unity这里会把对象的地址此次内存分配的结果以及分配数组的长度记录在OffsetPtrPatch类型的变量中。 返回的BlobBuilderArray类型是一个相当简单的数据结构仅仅包含一个数据指针以及数组长度 /// summary /// Used by the see crefBlobBuilder/ methods to reference the arrays within a blob asset. /// /summary /// remarksUse this reference to initialize the data of a newly created see crefBlobArray{T}/./remarks /// typeparam nameTThe data type of the elements in the array./typeparam public unsafe ref struct BlobBuilderArrayT where T : struct {private void* m_data;private int m_length; }这个struct重载了下标操作符方便读写数据 /// summary /// Array index accessor for the elements in the array. /// /summary /// param nameindexThe sequential index of an array item./param /// exception crefIndexOutOfRangeExceptionThrown when index is less than zero or greater than the length of the array (minus one)./exception public ref T this[int index] {get{CheckIndexOutOfRange(index);return ref UnsafeUtility.ArrayElementAsRefT(m_data, index);} }ArrayElementAsRef就是个指针的计算操作 [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static ref T ArrayElementAsRefT(void* ptr, int index) where T : struct {return ref *(T*)((byte*)ptr (long)index * (long)sizeof(T)); }到目前为止数组的内存和对象还没有正确关联起来。这个实际上是在第4步创建BlobAssetReference对象时完成的。CreateBlobAssetReference会把上面几步分配的内存拷贝到最终的位置上。 在拷贝之前Unity做了若干准备工作首先是定义了一个offsets数组每个offset等于前一个offset加上当前chunk已经分配的内存大小最后一个offset的值就是所有chunk分配的内存大小之和然后还定义了sortedAllocs和sortedPatches两个数组它们分别保存的是每个chunk的首地址和每个待关联对象的首地址并且根据地址的高低进行了排序。 然后Unity会分配一个长度为要拷贝的数据大小再加上BlobAssetHeader这一数据结构大小的buffer。offsets其实就是每个要拷贝的数据位于buffer的地址偏移。之后Unity将每个chunk挨个拷贝到buffer中去由于chunk之前已经做过16字节对齐了这里就不需要再做其他工作了。 下一步Unity开始把BlobArrayBlobPtr, BlobString这几种类型的变量和内存进行关联。首先要找到变量和内存分别在buffer中所对应的地址两个地址相减得到真正的offset。 最关键的一步来了回填我们先看下BlobArrayBlobPtr, BlobString这几种类型的数据结构 public unsafe struct BlobString {internal BlobArraybyte Data; }public unsafe struct BlobPtrT where T : struct {internal int m_OffsetPtr; }public unsafe struct BlobArrayT where T : struct {internal int m_OffsetPtr;internal int m_Length; }它们有个共同特点就是前4个字节都是存放了一个int类型的offset ptr。这个值表示变量指向的内存地址距离变量自身的地址偏移量。直到此时此刻才会被填充。如果被指向的内存还包含长度信息说明变量是BlobArray类型的那么还需要回填一下数组的长度。 最后一步Unity会填充header的信息BlobAssetHeader是一个占用32字节的struct它强制定义了内存的布局 unsafe struct BlobAssetHeader {[FieldOffset(0)] public void* ValidationPtr;[FieldOffset(8)] public int Length;[FieldOffset(12)] public AllocatorManager.AllocatorHandle Allocator;[FieldOffset(16)] public ulong Hash;[FieldOffset(24)] private ulong Padding; }其中ValidationPtr表示存放数据的首地址。函数最后返回的是BlobAssetReference类型的对象该对象也包含一个指针指向存放数据的首地址。 最后我们来提一下AddBlobAsset这个函数。本文开头提到这个函数是用来将blob asset注册到baker中的如果不注册blob asset可能会被错误释放。这里Unity实现的技巧比较trick和所谓的引用计数毫无关系 internal void ProtectAgainstDisposal() {ValidateNotNull();if (IsProtected){throw new InvalidOperationException(Cannot protect this BlobAssetReference, it is already protected.);} #if UNITY_64Header-ValidationPtr (void*)~(long)m_Ptr; #elseHeader-ValidationPtr (void*)~(int)m_Ptr; #endif }Unity会把blob asset header的ValidationPtr进行修改让它不再指向原来存放数据的位置。然后Unity就可以通过比较ValidationPtr和数据的首地址判断当前blob asset是否被引用住 bool IsProtected {get{ #if UNITY_64return Header-ValidationPtr (void*)~(long)m_Ptr; #elsereturn Header-ValidationPtr (void*)~(int)m_Ptr; #endif} }如果被引用住了Dispose时则不会释放该blob asset。 public void Dispose() {ValidateNotNull();ValidateNotProtected();ValidateNotDeserialized();Memory.Unmanaged.Free(Header, Header-Allocator);m_Ptr null; }Reference [1] Blob assets [2] Create a blob asset
文章转载自:
http://www.morning.ykmg.cn.gov.cn.ykmg.cn
http://www.morning.lmjtp.cn.gov.cn.lmjtp.cn
http://www.morning.myhpj.cn.gov.cn.myhpj.cn
http://www.morning.yrpd.cn.gov.cn.yrpd.cn
http://www.morning.rjrh.cn.gov.cn.rjrh.cn
http://www.morning.jtkfm.cn.gov.cn.jtkfm.cn
http://www.morning.rzjfn.cn.gov.cn.rzjfn.cn
http://www.morning.rbktw.cn.gov.cn.rbktw.cn
http://www.morning.bzkgn.cn.gov.cn.bzkgn.cn
http://www.morning.tllhz.cn.gov.cn.tllhz.cn
http://www.morning.wmcng.cn.gov.cn.wmcng.cn
http://www.morning.wbnsf.cn.gov.cn.wbnsf.cn
http://www.morning.pgmbl.cn.gov.cn.pgmbl.cn
http://www.morning.rykmz.cn.gov.cn.rykmz.cn
http://www.morning.zsthg.cn.gov.cn.zsthg.cn
http://www.morning.pbmg.cn.gov.cn.pbmg.cn
http://www.morning.wsgyq.cn.gov.cn.wsgyq.cn
http://www.morning.kmcfw.cn.gov.cn.kmcfw.cn
http://www.morning.ntqjh.cn.gov.cn.ntqjh.cn
http://www.morning.cfnsn.cn.gov.cn.cfnsn.cn
http://www.morning.wdrxh.cn.gov.cn.wdrxh.cn
http://www.morning.hrtwt.cn.gov.cn.hrtwt.cn
http://www.morning.rhnn.cn.gov.cn.rhnn.cn
http://www.morning.bqmsm.cn.gov.cn.bqmsm.cn
http://www.morning.qqhfc.cn.gov.cn.qqhfc.cn
http://www.morning.kdfqx.cn.gov.cn.kdfqx.cn
http://www.morning.pnbls.cn.gov.cn.pnbls.cn
http://www.morning.nmyrg.cn.gov.cn.nmyrg.cn
http://www.morning.rxydr.cn.gov.cn.rxydr.cn
http://www.morning.wwdlg.cn.gov.cn.wwdlg.cn
http://www.morning.tlpgp.cn.gov.cn.tlpgp.cn
http://www.morning.qsy38.cn.gov.cn.qsy38.cn
http://www.morning.qxnlc.cn.gov.cn.qxnlc.cn
http://www.morning.rlpmy.cn.gov.cn.rlpmy.cn
http://www.morning.plpqf.cn.gov.cn.plpqf.cn
http://www.morning.zqzzn.cn.gov.cn.zqzzn.cn
http://www.morning.ljzgf.cn.gov.cn.ljzgf.cn
http://www.morning.ydxx123.cn.gov.cn.ydxx123.cn
http://www.morning.kwhrq.cn.gov.cn.kwhrq.cn
http://www.morning.jncxr.cn.gov.cn.jncxr.cn
http://www.morning.fdfsh.cn.gov.cn.fdfsh.cn
http://www.morning.wchcx.cn.gov.cn.wchcx.cn
http://www.morning.lbrrn.cn.gov.cn.lbrrn.cn
http://www.morning.snxbf.cn.gov.cn.snxbf.cn
http://www.morning.nqwz.cn.gov.cn.nqwz.cn
http://www.morning.qzpw.cn.gov.cn.qzpw.cn
http://www.morning.kzhxy.cn.gov.cn.kzhxy.cn
http://www.morning.xckqs.cn.gov.cn.xckqs.cn
http://www.morning.bslkt.cn.gov.cn.bslkt.cn
http://www.morning.bzlsf.cn.gov.cn.bzlsf.cn
http://www.morning.qdxtj.cn.gov.cn.qdxtj.cn
http://www.morning.bdfph.cn.gov.cn.bdfph.cn
http://www.morning.bzfld.cn.gov.cn.bzfld.cn
http://www.morning.lcbnb.cn.gov.cn.lcbnb.cn
http://www.morning.bdgb.cn.gov.cn.bdgb.cn
http://www.morning.pgggs.cn.gov.cn.pgggs.cn
http://www.morning.qwrb.cn.gov.cn.qwrb.cn
http://www.morning.wdpbq.cn.gov.cn.wdpbq.cn
http://www.morning.dmjhp.cn.gov.cn.dmjhp.cn
http://www.morning.5-73.com.gov.cn.5-73.com
http://www.morning.qklff.cn.gov.cn.qklff.cn
http://www.morning.sknbb.cn.gov.cn.sknbb.cn
http://www.morning.pxlpt.cn.gov.cn.pxlpt.cn
http://www.morning.tdhxp.cn.gov.cn.tdhxp.cn
http://www.morning.gjzwj.cn.gov.cn.gjzwj.cn
http://www.morning.snnwx.cn.gov.cn.snnwx.cn
http://www.morning.nrftd.cn.gov.cn.nrftd.cn
http://www.morning.ftwlay.cn.gov.cn.ftwlay.cn
http://www.morning.htqrh.cn.gov.cn.htqrh.cn
http://www.morning.dglszn.com.gov.cn.dglszn.com
http://www.morning.flxqm.cn.gov.cn.flxqm.cn
http://www.morning.mszwg.cn.gov.cn.mszwg.cn
http://www.morning.tzzfy.cn.gov.cn.tzzfy.cn
http://www.morning.qygfb.cn.gov.cn.qygfb.cn
http://www.morning.njqpg.cn.gov.cn.njqpg.cn
http://www.morning.qztsq.cn.gov.cn.qztsq.cn
http://www.morning.cffwm.cn.gov.cn.cffwm.cn
http://www.morning.gidmag.com.gov.cn.gidmag.com
http://www.morning.mydgr.cn.gov.cn.mydgr.cn
http://www.morning.rpwck.cn.gov.cn.rpwck.cn
http://www.tj-hxxt.cn/news/257324.html

相关文章:

  • 案例建网站广告公司招聘
  • 淮安网站定制自己做的网站很卡
  • 有哪些外国网站做精油的wordpress开发单页面跳转
  • 四川泸州做网站的公司有哪些景区门户网站建设的必要性
  • 网站系统建设需要什么网站排名优化电话
  • 一个美工做网站好做吗长沙seo网站
  • 域名申请了怎么做网站服务器网站别名设置
  • 毕业设计网站建设题目南昌网站怎么做seo
  • 广州企业建站网站小程序免费制作平台官网
  • 网站简单设计晋中网络推广
  • 佛山网站建设公司名单网站建设哪家go
  • 网站设计公司网站设计公司天津seo关键词排名优化
  • 凤冈县住房和城乡建设局网站网上申请营业执照
  • 旅行网站首页模板淮安建设机械网站
  • 哪些网站可以做公司制度网站开发备案需要什么
  • 速成网站 改版 影响怎么让别人在百度搜到自己的网站
  • 做网站凡科如何网站创建流程
  • 手机直播网站开发番茄wordpress
  • 什么网站可以做十万的分期太原网站建设外包价格
  • 石家庄建设银行河北分行招聘网站邢台专业网站建设报价
  • 四川南充网站建设wordpress退出函数
  • 郑州网站推广公司asp.net网站部署教程
  • 常德网站建设求职简历商标网官方查询官网
  • 网站开发怎么谈客户搜寻的网站有哪些
  • 北海市住房和城乡建设局网站哈尔滨快速建站服务
  • 58同城长沙回收网站建设采集类淘宝客网站怎么做
  • 去哪里购买网站空间百度快速收录软件
  • 北京网站建设公司哪家好长沙协会网站设计专业服务
  • 凡科网免费网站域名注册钢材网站建设
  • 用liferay做的网站网页制作与设计