在前面数据绑定基本流程,简单说了下,在Axiom中,数据从我们C#的托管环境到下面的OpenGL或是D3D的非托管环境,有个转化过程,相关实现我们可以从BufferBase看起.BufferBase与他的子类集合了相关数据块在托管环境与非托管环境的相关操作.     在BufferBase中,包装了一个重要的类GCHandle,其中托管代码中,因为GC的关系,在运行时所有元素的内存地址也都是变化的,这里在我们需要用到GCHandleType.Pinned,这个会固定我们申请的空间地址,防止GC移动与释放这块内存,当然这块内存的回收也和C++里一样,需要我们手动调用Free方法去释放.GCHandle对象保存了数据块在内存中的位置,而GCHandle里的Ptr(int)保存的是我们在GCHandle内存块里的位置(如申请100字节长度,那么Ptr只能是0-99这100百个数),默认是头0开始,一般用来做偏移地址运算.BufferBase提供一个虚拟方法Pin(),供子类提供数据块固定的指针地址,以便于OpenGL,D3D中非托管环境调用.最后BufferBase里的方法Wrap,用来直接生成一个UnsafeBuffer的对象.

下面针对UnsafeBuffer,我们来先看一段代码:

这段代码里,我们首先用GCHandle.Alloc申请一块buffer大小的空间,在这buffer虽然是object类型,但是因为我们申请的是固定的句柄(GCHandleType.Pinned),这个是不支持引用类型的,就是buffer必需是值类型(值类型也有要求,应该说是准确声明空间长度的值类型),不过在Axiom中,我们一般是传递如int[],float[]这种,所以此处满足.申请后,我们用方法AddrofPinnedObject得到用Pinned方式申请的指针,上面this.Buf是成byte*块,就是字节块,这样主要是为了好做相关地址运算,如下面我传入一个-100.0,-100.0,0.0...的数组,请看下面相关结果.

表达式

内存地址

地址求值

(float*)this.Buf

0x01fdfab4

*((float*)this.Buf): -100.0

(float*)this.Buf + 1

0x01fdfab8

*((float*)this.Buf + 1): -100.0

(float*)this.Buf + 2

0x01fdfabc

*((float*)this.Buf + 2): 0.0

(float*)(this.Buf+4)

0x01fdfab8

*((float*)(this.Buf+4)): -100.0

(float*)(this.Buf+8)

0x01fdfabc

*((float*)(this.Buf+8)): 0.0

我们知道内存中,数据全是0101这样的bit位,我们的数组buffer保存在内存中也是这样,我们平常定义的什么int,float,byte等只是为了让计算机正确解析位来转换成相应数据.这里转换成byte*,float*,int*的区别也是这样,如果转化成byte位,那么他加1就是一个byte,同理,他转化成int,float,他就加4个byte,也就是4个字节长度.我们知道sizeof计算的长度就是字节来算的,这里转化成byte*就是用了容易对地址进行定义,因为字节是我们数据块用到的最小单位,对应属性Length长度指的也是字节.如上,转化成byte*后,我要得到第二个float就用(float*)(this.Buf+4)或是(float*)this.buf+1,效果一样.我们再来看下面一段代码就很清楚了.

我们知道,long是8个字节,而index是指单位为字节的长度,那么转化成对应的long数组里对应的long的索引应该是index*8,例如index是10,那么long数组对应值应该是对应字节块的初地址加上80的偏移量.对应的如ITypePointer<byte>,ITypePointer<short>,ITypePointer<int,float>,ITypePointer<double>分别是index,index*2,index*4,index*8.

而同属BufferBase的子类的ManagedBuffer,不同于UnsafeBuffer管理的byte*,他管理的是byte[],好吧,这二个也是一样,相关的索引器也是在对byte索引的偏移计算,同UnsafeBuffer逻辑一样,不同的是,UnsafeBuffer中的GCHandle.Alloc操作是在初始化的时候.而ManagedBuffer是发生在调用方法Pin时,才会执行GCHandle.Alloc操作.注意,不管是UnsafeBuffer还是ManagedBuffer,Pin方法指向的指针位置是当前内存块的头地址(GCHandle.AddrofPinnedObject())加上偏移地址(BufferBase.Ptr).

同样如ManagedBufferCol3b等,都是在原来类的基础上增加一个对应的索引器.

在前面Axiom3D:数据绑定基本流程可以看到顶点数据(VertexData),索引数据(IndexData),他们都有HardwareBuffer对象,这个对象用来与BufferBase互动.HardwareBuffer与BufferBase的关系有些类似AnimationTrack与KeyFrame,他们的具体实现交给子类,抽象互动都由本身来实现.前面我们说了BufferBase,主要是提供一个数据块空间,这个空间的位置,对这个空间的索引,相关子类对应托管环境与非托管环境的实现.而HardwareBuffer如下方法WriteData,ReadData,Copy分别提供对BufferBase的写入,读取,复制数据一些操作的包装.针对GL的环境,我们来看下HardwareBuffer的子类GLHardwareVertexBuffer,其WriteData,ReadData就是调用glBufferData,glGetBufferData分别把BufferBase里的数据块写入到显存,或从显存中读取出来.不用显存,DefaultHardwareVertexBuffer提供针对内存中BufferBase的相关操作,不像GLHardwareVertexBuffer需要把数据从CPU到GPU的过程,DefaultHardwareVertexBuffer里的读取,写入,复制操作就是把BufferBase的数据块从一个地方复制到另一个地方,直接用的就是对应的BufferBase的Copy操作.

还有一个地方,数据也是一块一块的包装在一个位置的,就是纹理,我们知道纹理图片里的每个像素点都是各个类型的RGBA元素组合而成,那么在我们内存或显存中,图片就是一个数据块区域,知道了这个数据块区域的格式,如RGBA8B,那么我们就能正确的解析成相应的像素点集合,然后就能正确的在显示器上显示成对应图像了.通过纹理我们能利用GPU强大的并行功能,因为纹理就是数据块,就是数组.具体可以参看GPGPU基本运算与乒乓技术.

如同顶点对应HardwareVertexBuffer,顶点索引对应HardwareIndexBuffer,图片也有自己的HardwareBuffer对应类HardwarePixelBuffer.在介绍这个类时,先看下类BasicBox与PixelBox,其中PixelBox是BasicBox的子类,BasicBox差不多就是针对一个描述一个立方体,有6面,分别是前后左右上下6面(一般情况下,默认宽度Width指左右距离,高度Height指上下距离,深度Depth指前后距离).而PixelBox描述的是图片(包含一维至三维,一维用宽度Width,二维增加高度Height,三维增加深度Depth).在BasicBox的上面增加一个BufferBase用来表示像素数据,其中PixelBox有个比较重要的属性PixelFormat,其实这个类就相当于VertexDeclaration,一个是指明像素是如何组成的,如SHORT_RBG.而VertexDeclaration指明顶点是如何组成,如T2fN3fV3f.有了PixelFormat,我们才能正确序列化PixelBox里的数据块BufferBase里的信息.在PixelConverter这个类中提供了二个PixelBox互相操作的方法,例如从一张图片中提取他的R通道数据,调用PixelConverter的BulkPixeConversion方法就可.有兴趣可以看一下具体实现,本质还是对BufferBase根据PixelFormat与索引得到偏移赋值操作.

  而HardwarePixelBuffer提供二个抽象方法,一个是BlitFormMemory,把PixelBox中的像素数据取出放到新的内存或显存.另一个是BlitToMemory,把显存和内存里的数据取出.这二个函数分别在GL的环境中的子类GLHardwareBuffer与他的子类GLTextureBuffer中的实现如下,BlitFormMemory就是调用GL的API如glTexImage2D这类把数据,而BlitToMemory就是调用glGetTexImage,这样就很容易理解了.

  下图是上面类的关系,突出像素HardwarePixelBuffer与BufferBase的关系。

Axiom3D:Buffer漫谈的更多相关文章

  1. Axiom3D:Ogre地形组件代码解析

    大致流程. 这里简单介绍下,Axiom中采用的Ogre的地形组件的一些概念与如何生成地形. 先说下大致流程,然后大家再往下看.(只说如何生成地形与LOD,除高度纹理图外别的纹理暂时不管.) 1.生成T ...

  2. Axiom3D:数据绑定基本流程

    在前面我们学习OpenGL时,不管绘制如球,立方体,平面,地面,动画模型中最常用的几个操作有创建缓冲区,写入缓冲区.在Axiom中,相关的操作被整合与组织到VertexData,IndexData中, ...

  3. MySQL · 性能优化· InnoDB buffer pool flush策略漫谈

    MySQL · 性能优化· InnoDB buffer pool flush策略漫谈 背景 我们知道InnoDB使用buffer pool来缓存从磁盘读取到内存的数据页.buffer pool通常由数 ...

  4. 【转载】MySQL · 性能优化· InnoDB buffer pool flush策略漫谈

    背景 我们知道InnoDB使用buffer pool来缓存从磁盘读取到内存的数据页.buffer pool通常由数个内存块加上一组控制结构体对象组成.内存块的个数取决于buffer pool inst ...

  5. 【转】漫谈linux文件IO--io流程讲的很清楚

    [转]漫谈linux文件IO--io流程讲的很清楚 这篇文章写的比较全面,也浅显易懂,备份下.转载自:http://blog.chinaunix.net/uid-27105712-id-3270102 ...

  6. Axiom3D写游戏:用Overlay实现Mesh浏览.

    从网上找了些资源,大多搜Ogre,Mesh资源,然后为了方便查看各个Mesh,以及对应骨骼动画.为了实用性,考虑放在原游戏窗口里实现.最开始打算窗口新建viewport来实现,后发现这种方式的局限性, ...

  7. (转)漫谈JVM

    漫谈JVM 原文:https://liuzhengyang.github.io/2016/10/05/gossip-jvm/ 背景介绍 JVM已经是Java开发的必备技能了,JVM相当于Java的操作 ...

  8. 分布式系统漫谈一 —— Google三驾马车: GFS,mapreduce,Bigtable

    分布式系统学习必读文章!!!! 原文:http://blog.sina.com.cn/s/blog_4ed630e801000bi3.html 分布式系统漫谈一 —— Google三驾马车: GFS, ...

  9. [Alink漫谈之三] AllReduce通信模型

    [Alink漫谈之三] AllReduce通信模型 目录 [Alink漫谈之三] AllReduce通信模型 0x00 摘要 0x01 MPI是什么 0x02 Alink 实现MPI的思想 0x03 ...

随机推荐

  1. git报错之index.lock

    当想回退到某个版本的时候,用git reset --hard commit_id,发现报错,原因是.git目录下多了个index.lock文件,可以通过rm命令删除,然后再回退 rm -f ./.gi ...

  2. PC-Lint概念与基本操作

    1.   PC-Lint工具介绍 PC-Lint for C/C++是由Gimpel软件公司于1985年开发的代码静态分析工具,它能有效地发现程序语法错误.潜在的错误隐患.不合理的编程习惯等. C语言 ...

  3. Android环境搭建问题的解决: Connection to http://dl-ssl.google.com refused

    第一次搭建Android环境,遇到这个问题: Fetching http://dl-ssl.google.com/android/repository/addons_list-1.xmlFailed  ...

  4. git stash 暂存恢复和文件误删恢复

    git commit提交文件,服务器返回本地文件有修改. 1.git stash :暂存本地代码 2.git pull origin develop : 获取远程分支代码 3.git stash po ...

  5. Docker实战-编写Dockerfile

    一.编译镜像 1. 编译镜像 Dockerfile类似于Makfile,用户使用docker build就可以编译镜像,使用该命令可以设置编译镜像时使用的CPU数量.内存大小.文件路径等 语法:doc ...

  6. Python实例获取mp3文件的tag信息

    下面利用一个python的实例程序,来学习python.这个程序的目的就是分析出所有MP3文件的Tag信息并输出. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ...

  7. C#学习笔记(20)——使用IComparer(自己写的)

    说明(2017-7-25 10:38:37): 1. 参照了上一篇百度文库里的文章. 2. 总结来看,Icomparer就是sort方法的一个参数,用来自定义一个排序规则. 3. 使用方法是,定义一个 ...

  8. ubuntu 12.04下编译安装nginx-1.9.3

    1,下载nginx-1.9.3.tar.gz 两种方式: (1).ubuntu 下终端中(ctrl+alt+t) 运行命令: wget http://nginx.org/download/nginx- ...

  9. thinkphp继承高级model后的乐观锁运用(测试中)

    <?php class IndexAction extends Action { private $d_user; private $user; private $arr; public fun ...

  10. 调整Intellij IDEA内存

    最近IDEA真是卡的要死,下面