Axiom3D:Buffer漫谈
在前面数据绑定基本流程,简单说了下,在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漫谈的更多相关文章
- Axiom3D:Ogre地形组件代码解析
大致流程. 这里简单介绍下,Axiom中采用的Ogre的地形组件的一些概念与如何生成地形. 先说下大致流程,然后大家再往下看.(只说如何生成地形与LOD,除高度纹理图外别的纹理暂时不管.) 1.生成T ...
- Axiom3D:数据绑定基本流程
在前面我们学习OpenGL时,不管绘制如球,立方体,平面,地面,动画模型中最常用的几个操作有创建缓冲区,写入缓冲区.在Axiom中,相关的操作被整合与组织到VertexData,IndexData中, ...
- MySQL · 性能优化· InnoDB buffer pool flush策略漫谈
MySQL · 性能优化· InnoDB buffer pool flush策略漫谈 背景 我们知道InnoDB使用buffer pool来缓存从磁盘读取到内存的数据页.buffer pool通常由数 ...
- 【转载】MySQL · 性能优化· InnoDB buffer pool flush策略漫谈
背景 我们知道InnoDB使用buffer pool来缓存从磁盘读取到内存的数据页.buffer pool通常由数个内存块加上一组控制结构体对象组成.内存块的个数取决于buffer pool inst ...
- 【转】漫谈linux文件IO--io流程讲的很清楚
[转]漫谈linux文件IO--io流程讲的很清楚 这篇文章写的比较全面,也浅显易懂,备份下.转载自:http://blog.chinaunix.net/uid-27105712-id-3270102 ...
- Axiom3D写游戏:用Overlay实现Mesh浏览.
从网上找了些资源,大多搜Ogre,Mesh资源,然后为了方便查看各个Mesh,以及对应骨骼动画.为了实用性,考虑放在原游戏窗口里实现.最开始打算窗口新建viewport来实现,后发现这种方式的局限性, ...
- (转)漫谈JVM
漫谈JVM 原文:https://liuzhengyang.github.io/2016/10/05/gossip-jvm/ 背景介绍 JVM已经是Java开发的必备技能了,JVM相当于Java的操作 ...
- 分布式系统漫谈一 —— Google三驾马车: GFS,mapreduce,Bigtable
分布式系统学习必读文章!!!! 原文:http://blog.sina.com.cn/s/blog_4ed630e801000bi3.html 分布式系统漫谈一 —— Google三驾马车: GFS, ...
- [Alink漫谈之三] AllReduce通信模型
[Alink漫谈之三] AllReduce通信模型 目录 [Alink漫谈之三] AllReduce通信模型 0x00 摘要 0x01 MPI是什么 0x02 Alink 实现MPI的思想 0x03 ...
随机推荐
- Android 源码阅读笔记
Zygote: .Zygote 是系统启动之后创建的第二个进程2.Zygote 创建zygote Socket.虚拟机3.Zygote 在虚拟机中通过forkSystemServer, 创建Serve ...
- C#中自定义属性的例子
自定义属性的作用 有时候我们需要给一个类或者类中的成员加上一些属性或者附加信息,让类或者变量的功能更明确可控制的细粒度更高,打个简单的比方:数据库里面的一张表,表中的每一个字段都有很多属性,如是否主键 ...
- HTML5学习笔记(六):CSS基本样式
背景 需要注意:背景的所有属性都不会向下进行继承. 背景色 我们可以设定一个纯色为背景色. p {background-color: red;} a {background-color: #ff000 ...
- How do I measure JVM startup time?
https://stackoverflow.com/questions/39321345/how-do-i-measure-jvm-startup-time PrintCompilation2 htt ...
- 微信小程序启动过程分析
1.微信客户端在打开小程序之前,会把整个小程序的代码包下载到本地. 2.紧接着通过 app.json 的 pages 字段就可以知道你当前小程序的所有页面路径: { "pages" ...
- python(56):正则表达式积累
来源:http://www.runoob.com/python/python-reg-expressions.html re.match函数 re.match 尝试从字符串的起始位置匹配一个模式,如果 ...
- 安装VCSA6.5(vCenter Server Appliance 6.5)
相关文章:http://www.ctoclubs.com/?p=756 一.简介 VCSA(vCenter Server Appliance 6.5),相对于Windows版本的vCenter,VCS ...
- spring c3p0 配置
spring c3p0 配置 <?xml version="1.0" encoding="UTF-8"?> <beansxmlns=& ...
- DjangoUeditor 使用七牛云存储
DjangoUeditor 是一个相当赞的django 富文本编辑器,你可以在 https://github.com/zhangfisher/DjangoUeditor 查看相关信息. 我一直想着把D ...
- redis集群主流架构方案分析
Redis在互联网大数据平台有着广泛的应用,主要被用来缓存热点数据,避免海量请求压垮数据库,同时可以提升服务节点的响应速度和并发量.随着数据量的增多,由于redis是占用单台物理机或虚机的内存,内存资 ...