D3D的内存类型
三种内存AGP内存(非本地显存),显存(本地内存),系统内存,其中我们都知道系统内存就是咱那内存条,那这AGP内存是个啥玩意啊?其实是因为在以前显卡内存都很小,那时还是在显存是16M,32M为主流的时候,如果你运行一个需要很多纹理的3D程序,那么显存一会就不够用了,那该咋办呢?只好问系统内存借点用用了!这就是AGP内存的由来, 在我们电脑BIOS中有个设置AGP Aperture的选项,这里就是设置显卡可以使用系统内存的最大允许值,通常是设置为64M。注意,这里只是说最 大允许值,并不是一开机他就把这64M给拿走了,你的256内存就变成192了!而是你的内存依然还是256M,只是限制显卡最多可以使用64M的系统内 存。
再说说这三个内存的速度的不同吧!
系统内存当然是人家CPU读和写操作最快啦!而显卡就会相对于使用自己的显存慢上很多很多!
AGP内存是显卡读和写的速度一般,当然肯定没
有显卡使用显存速度快啦!CPU就相对复杂点了,CPU读取AGP内存速度很慢,但是写的速度却并不会慢,而是速度一般,比使用系统内存慢那么一点,也就
是说适合CPU去写但不适合读。有人就要问了,同样是系统内存只不过名字不一样,咋速度的就有差别了呢?这个嘛,我也不太清楚,老外没有说的太详细,大家
只要记住就行了!
最后说的就是显存了,这个很简单,当然是显卡读和写的速度最快,而CPU读和写的速度肯定要慢好多的!
说了三个内存的区别,现在说说他们都有什么用处吧!这里涉及一个D3DUSAGE枚举量:
D3DUSAGE_DYNAMIC,这个变量是在你创建资源时使用到的,它指示D3D将资源指定为动态的,而动态的意思就是需要经常修改,修改通常是CPU进行修改,所以动态资源应该放在AGP内存中。这样对速度的影响可以减至最小。
D3DUSAGE_WRITEONLY标志您所创建的资源只允许写操作。使用这个标志可以让设备将这个资源放到内存中最适合进行写处理和渲染的区
域。如果没有使用D3DUSAGE_WRITEONLY标志,那么设备将假设您创建的资源既用来读也用来写,那么设备将很可能选择一块内存区域,读和写操
作的速度都适中的地方。这将牺牲一部分处理和渲染速度。
对D3DLOCK的标志和资源创建类型也有影响
但是三种内存是另外一种优化访问的方法,因为比如粒子系统就需要使用AGP内存,因为他需要CPU经常进行修改,又需要图形处理卡经常读取,如果放在显存那么CPU修改的效率太低了!如果放在内存,那么图形处理卡访问的速度太慢!所以这三种内存还是需要分别清楚的!
D3DPOOL定义了资源对应的内存类型,资源可以是texture surface, vertex buffer等,有以下几种POOL类型
D3DPOOL_DEFAULT
D3DPOOL_MANAGED
D3DPOOL_SYSTEMMEM
D3DPOOL_SCRATCH
D3DPOOL_FORCE_DWORD
D3DPOOL_DEFAULT
资源被存储在最适合给定资源访问的内存中,这通常是显存,包括本地显内存和AGP内存,D3DPOOL_DEFAULT不同于 D3DPOOL_MANAGED和D3DPOOL_SYSTEMMEM,它指出了资源被存储在最适合设备访问的内存中,D3DPOOL_DEFAULT指 出D3DPOOL_MANAGED和D3DPOOL_SYSTEMMEM永远都不会作为资源内存的备选类型,使用D3DPOOL_DEFAULT分配的纹 理资源是无法锁定的,除非该纹理是动态纹理或者是私有的FOURCC driver 格式。想要访问无法锁定的纹理资源,必须使用如下函数
IDirect3DDevice9::UpdateSurface
IDirect3DDevice9::UpdateTexture
IDirect3DDevice9::GetFrontBufferData
IDirect3DDevice9::GetRenderTargetData
对大多数应用程序来说,使用D3DPOOL_MANAGED是一个更好的选择。一些使用driver特有的像素格式创建的纹理,无法被 Direct3D runtime识别,也是可以锁定的。与texture不同的是,swap chain back buffers, render targets, vertex buffers和index buffers都是可以锁定的,当设备丢失时,所有使用D3DPOOL_DEFAULT创建的资源必须在调用Reset函数前释放掉,使用 D3DPOOL_DEFAULT创建资源时,如果内存不够用,那么managed resource会释放一些内存空间来满足需要。
D3DPOOL_MANAGED
资源按需自动被拷贝到设备能访问的内存中。托管资源由系统内存备份,所以设备丢失时无需重建。托管资源可以被锁定,只有系统备份的那份内存能直接被修改。Direct3D按需将修改拷贝到设备可访问的内存中。
D3DPOOL_SYSTEMMEM
资源被分配在不能被设备直接访问的内存中。这些内存消耗系统的RAM但是并不减少可分页的RAM。这些资源不必在设备丢失时重建。这种资源也可以被 锁定,并且可以用作函数IDirect3DDevice9::UpdateSurface或 IDirect3DDevice9::UpdateTexture的源,这两个函数的操作目标都是D3DPOOL_DEFAULT类型的资源。
D3DPOOL_SCRATCH
资源分配在系统RAM中并且无需在设备丢失时重建。这种资源不受设备大小和格式的限制。因此,这种资源不能被Direct3D设备使用,也不能设置为纹理或者Render targets,尽管如此,这种资源也可以被创建,锁定和拷贝。
D3DPOOL_FORCE_DWORD
强制该类型编译为32bit大小,没有这个值,一些编译器将会把这个枚举类型编译为非32bit大小的类型,该值暂未使用。
所有的内存类型适用于所有的资源类型,包括Vertex Buffers, Index Buffers, textures和Surfaces
下面的表指出了资源的内存类型及用法之间的兼容关系,x表示兼容
同一个资源中的不同对象间的资源池不能混合(mip levels in a mipmap),并且当一个资源池被选中时就不能被改变了。
对于大多数静态资源,应用程序应该使用D3DPOOL_MANAGED,因为这使得应用程序不必处理设备丢失。这在统一内存架构的系统(UMA)上
显得尤为有益。其他动态资源类型并不适合使用D3DPOOL_MANAGED,实际上,index buffers和vertex
buffers不能同时使用D3DPOOL_MANAGED和D3DUSAGE_DYNAMIC创建。
对于动态纹理,有时需要使用一对内存,一个是使用D3DPOOL_DEFAULT分配的显存,另一个是使用D3DPOOL_SYSTEMMEM分配
的系统内存。可以用锁定的方法在系统内存上修改纹理,并使用函数IDirect3DDevice9::UpdateTexture将修改更新到显存中。
D3D资源管理
资源分类
顶点缓冲(VertexBuffer)
索引缓冲(IndexBuffer)
纹理(Texture)
资源存储
显存(Video Memory)
通过AGP直接访问的内存(AGP Aperture,也叫做非本地显存)
系统内存(System Memory)
性能权衡
我们在创建D3D资源的时候需要填写两个参数:D3DPOOL、D3DUSAGE。这两个参数共同决定了资源最终存储在显存、非本地显存还是系统内存中。
枚举类型D3DPOOL
D3DPOOL_DEFAULT
D3DPOOL_MANAGED
D3DPOOL_SYSTEMMEM
D3DPOOL_SCRATCH
D3DPOOL_MANAGED:
资源存储位置:由D3D内部管理此资源,此类资源通常被创建在系统内存中。在显卡需要此资源时,D3D将它从内存拷贝到显存。
当设备丢失时,D3D会自动恢复显存中的数据。
适用情况:由于D3D自己的资源管理方案很高效、使用简单,游戏中大部分资源都可以使用此标识创建。
例子:游戏中使用的大部分纹理贴图,静态模型。
D3DPOOL_DEFAULT:
资源存储位置:此类资源不由D3D管理,通常被创建在显存或AGP Aperture中。
当设备丢失时,必需手动恢复资源,增加了代码复杂度。
适用情况:有时候我们希望将某些资源一直放在显存里,以提高访问速度。同时使用D3DUSAGE_WRITEONLY标记会提高效率。
例子:游戏中使用的光标贴图,在游戏运行过程中一直要使用,可以直接创建在显存中。
如果数据需要高频率更新(不断的Lock, Unlock),也需要使用D3DPOOL_DEFAULT,同时使用D3DUSAGE_DYNAMIC标记。这意味着此资源会被创建在AGP Aperture中。
例子:使用CPU进行物理运算的粒子系统、使用CPU计算蒙皮的骨骼动画。
上图显示了使用不同USAGE和POOL参数创建资源的存储情况。
一个例子:Direct3D绘制简单图形 绘制立方体。
[Copy to clipboard]
CODE:
//创建顶点缓冲
if(FAILED(g_pD3DDevice->CreateVertexBuffer(3*sizeof(CUSTOMVERTEX),
0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVertexBuffer,NULL)))
{
return E_FAIL;
}
此代码使用D3DPOOL_DEFAULT 创建VertexBuffer,但是USAGE没有指定为D3DUSAGE_WRITEONLY,这样会造成严重的性能损失。应改为:
[Copy to clipboard]
CODE:
//创建顶点缓冲
if(FAILED(g_pD3DDevice->CreateVertexBuffer(3*sizeof(CUSTOMVERTEX),
D3DUSAGE_WRITEONLY, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT,
&g_pVertexBuffer,NULL)))
{
return E_FAIL;
}
D3D的内存类型的更多相关文章
- MTRR内存类型范围寄存器
1.MTRR的概念 内存类型范围寄存器(MTRRs,翻译过来真别扭,后面都以MTRR直接来说了)提供了一种机制,这种机制其实就是确定在系统内存中物理一段内存的类型.这个类型其实是正对CPU来说的,见图 ...
- 关于内存类型 UDIMM、RDIMM、LRDIMM 的学习结论(转)
随着内存技术不断发展,服务器上内存的容量.密度和速度也越来越高.目前在市场上出现的内存条最高密度可以做到每条内存条 4 个 Rank,容量达到 32GB/条,最高速度达到 1.6GHz.高密度高频率也 ...
- Python3 基本类型在64位上的占用内存情况
基本类型占用的内存 类型 # -*- coding: utf-8 -*- # @Time : 2019-12-19 11:16 # @Author : binger import sys a = No ...
- 【嵌入式开发】裸机引导操作系统和ARM 内存操作 ( DRAM SRAM 类型 简介 | Logical Bank | 内存地址空间介绍 | 内存芯片连接方式 | 内存初始化 | 汇编代码示例 )
[嵌入式开发]ARM 内存操作 ( DRAM SRAM 类型 简介 | Logical Bank | 内存地址空间介绍 | 内存芯片连接方式 | 内存初始化 | 汇编代码示例 ) 一. 内存 ...
- Linux内核笔记——内存管理之slab分配器
内核版本:linux-2.6.11 内存区和内存对象 伙伴系统是linux用于满足对不同大小块内存分配和释放请求的解决方案,它为slab分配器提供页框分配请求的实现. 如果我们需要请求具有连续物理地址 ...
- .NET Memory Profiler 查看内存使用情况
1 简介 .Net Memory Profiler(以下简称Profiler):专门针对于.NET程序,功能最全的内存分析工具,最大的特点是具有内存动态分析(Automatic Memory Anal ...
- 6个重要的.NET概念:栈,堆,值类型,引用类型,装箱,拆箱
引言 本篇文章主要介绍.NET中6个重要的概念:栈,堆,值类型,引用类型,装箱,拆箱.文章开始介绍当你声明一个变量时,编译器内部发生了什么,然后介绍两个重要的概念:栈和堆:最后介绍值类型和引用类型,并 ...
- C#内存管理与垃圾回收
垃圾回收还得从根说起,就像生儿育女一样. 根:根是一个位置,存放一个指针,该指针指向托管堆中的一个对象,或是一个空指针不指向任何对象,即为null.根存在线程栈或托管堆中,大部分的跟都在线程栈上,因为 ...
- C++内存分配及变长数组的动态分配
//------------------------------------------------------------------------------------------------ 第 ...
随机推荐
- android 入门 004 (同一个方法,点击实现不同的效果)
同一个方法,点击实现不同的效果 <Button android:id="@+id/btn3" android:layout_width="wrap_content& ...
- ContentProvider官方教程(5)ContentResolver插入、更新、删除 示例
Inserting, Updating, and Deleting Data In the same way that you retrieve data from a provider, you a ...
- javaweb的开发模式
SUN公司推出JSP技术后,同时也推荐了两种web应用程序的开发模式,一种是JSP+JavaBean模式,一种是Servlet+JSP+JavaBean模式. 一.JSP+JavaBean开发模式 1 ...
- 学习笔记TimePicker
new TimePickerDialog(this, new OnTimeSetListener() { @Override public void onTimeSet(TimePicker view ...
- include_path详细解析
include_path详细解析 原文地址:http://www.laruence.com/2010/05/04/1450.html 1.php默认的包含路径为 .;C:\php\pear 即 ...
- VBA中方法的函数式调用和过程式调用的差别
因见到有人求助批量设置工作簿中的超链接,尝试写了一段代码: Sub AddHyperlinks() Dim strName As String, source As String, target As ...
- vimperator学习教程
有人总是说Vim难学,而Vimperator把火狐变成了VIM,所以很多人就认为只有那些VIM的狂热者才会用这个插件,但实际上并不是这样.Vimperator在安装之后,只要稍加练习,就可以让我们的浏 ...
- Java开发中经典的小实例-(随机数)
import java.util.Random;//输出小于33的7个不相同的随机数public class probability { static Random random = new R ...
- Spring与其他Web框架集成
Spring与多种流行Web应用框架(Struts.JSF和DWR)集成的方法. Spring强大的IoC容器和企业支持特性使其十分适于实现Java EE应用的服务和持续层. 对于表现层,可以在许多不 ...
- WPF GroupBox样式
来源:http://code.msdn.microsoft.com/WPF-GroupBox-Style-1d9df7c5/ 效果: XAML CODE: <Window xmlns=" ...