如何从 Direct3D 11 中的 CPU 访问帧缓冲区?
How to access framebuffer from CPU in Direct3D 11?
我正在创建一个简单的框架来教授 C++/D3D11 下的基本图形概念。该框架需要通过一个简单的接口函数(例如Putpixel( x,y,r,g,b )
)直接操作屏幕光栅内容。
在 D3D9 下,这是一个相对简单的目标,通过在 CPU 构成表面的堆上分配表面缓冲区来实现。然后后备缓冲区将被锁定,堆缓冲区的内容将转移到后备缓冲区。据我了解,无法直接从 D3D11 下的 CPU 访问后备缓冲区。必须准备一个纹理资源,然后通过一些全屏几何图形将其绘制到后台缓冲区。
我已经为这样的程序考虑了两个系统。第一个包含 D3D11_USAGE_DEFAULT
纹理和 D3D11_USAGE_STAGING
纹理。暂存纹理首先被映射,然后从 CPU 绘制。当场景完成时,暂存纹理被取消映射并使用 CopyResource
复制到默认纹理(如果我没记错的话,它使用 GPU 执行复制),然后默认纹理通过绘制到后台缓冲区全屏纹理四边形。
第二个系统包括一个D3D11_USAGE_DYNAMIC
纹理和一个分配在堆上的帧缓冲区。当场景合成时,动态纹理被映射,堆缓冲区的内容通过 CPU 复制到动态纹理,动态纹理被取消映射,然后通过全屏绘制到后台缓冲区纹理四边形。
我的印象是使用读写访问和 D3D11_USAGE_STAGING
创建的纹理将驻留在系统内存中,但我进行的性能测试 运行 似乎表明情况并非如此.也就是说,通过 CPU 绘制一个简单的 200x200 填充矩形比使用堆缓冲区慢大约 3 倍(两种情况完全相同的反汇编(紧密 rep stos
循环)),强烈暗示暂存纹理驻留在图形适配器内存中。
我更愿意使用暂存纹理系统,因为它可以将渲染到后台缓冲区的工作和从系统内存复制到图形内存的工作都卸载到 GPU 上。但是,无论如何,我想 CPU 优先考虑访问速度而不是这种能力。
那么哪种方法最适合这种用例?任何提示、对我的两种方法的修改或对完全不同方法的建议都将不胜感激。
动态和暂存都可能在系统内存中,但它们很可能是您的问题,是写入组合内存。这是一种缓存模式,其中单个写入合并在一起,但如果您尝试读取,因为它是未缓存的,每次加载都需要付出完整内存访问的代价。你甚至必须非常小心,因为 c++ *data=something;
有时也会导致不需要的读取。
动态贴图没什么问题,GPU可以读取系统内存,但是需要小心,多创建几个,每帧循环一次map_nooverwrite,抑制代价高昂丢弃的驱动程序缓冲区重命名。当然,永远不要在读写中做映射,只写,否则你会引入 gpu/cpu 同步并杀死并行性。
最后,如果你想要一个持久的表面并且每帧只有几个 putpixel(或者甚至很多),我会选择一个无序访问视图和一个计算着色器,它消耗一个带有颜色的像素位置缓冲区更新。该缓冲区将再次成为一个没有覆盖映射的动态缓冲区。使用该解决方案,主表面将驻留在显存中。
就个人而言,我什至懒得教 cpu 表面操作,这几乎总是一种糟糕的做法和性能杀手,而不是现代 gpu 架构的方式。这在十年前还不是一个基本的图形概念。
我正在创建一个简单的框架来教授 C++/D3D11 下的基本图形概念。该框架需要通过一个简单的接口函数(例如Putpixel( x,y,r,g,b )
)直接操作屏幕光栅内容。
在 D3D9 下,这是一个相对简单的目标,通过在 CPU 构成表面的堆上分配表面缓冲区来实现。然后后备缓冲区将被锁定,堆缓冲区的内容将转移到后备缓冲区。据我了解,无法直接从 D3D11 下的 CPU 访问后备缓冲区。必须准备一个纹理资源,然后通过一些全屏几何图形将其绘制到后台缓冲区。
我已经为这样的程序考虑了两个系统。第一个包含 D3D11_USAGE_DEFAULT
纹理和 D3D11_USAGE_STAGING
纹理。暂存纹理首先被映射,然后从 CPU 绘制。当场景完成时,暂存纹理被取消映射并使用 CopyResource
复制到默认纹理(如果我没记错的话,它使用 GPU 执行复制),然后默认纹理通过绘制到后台缓冲区全屏纹理四边形。
第二个系统包括一个D3D11_USAGE_DYNAMIC
纹理和一个分配在堆上的帧缓冲区。当场景合成时,动态纹理被映射,堆缓冲区的内容通过 CPU 复制到动态纹理,动态纹理被取消映射,然后通过全屏绘制到后台缓冲区纹理四边形。
我的印象是使用读写访问和 D3D11_USAGE_STAGING
创建的纹理将驻留在系统内存中,但我进行的性能测试 运行 似乎表明情况并非如此.也就是说,通过 CPU 绘制一个简单的 200x200 填充矩形比使用堆缓冲区慢大约 3 倍(两种情况完全相同的反汇编(紧密 rep stos
循环)),强烈暗示暂存纹理驻留在图形适配器内存中。
我更愿意使用暂存纹理系统,因为它可以将渲染到后台缓冲区的工作和从系统内存复制到图形内存的工作都卸载到 GPU 上。但是,无论如何,我想 CPU 优先考虑访问速度而不是这种能力。
那么哪种方法最适合这种用例?任何提示、对我的两种方法的修改或对完全不同方法的建议都将不胜感激。
动态和暂存都可能在系统内存中,但它们很可能是您的问题,是写入组合内存。这是一种缓存模式,其中单个写入合并在一起,但如果您尝试读取,因为它是未缓存的,每次加载都需要付出完整内存访问的代价。你甚至必须非常小心,因为 c++ *data=something;
有时也会导致不需要的读取。
动态贴图没什么问题,GPU可以读取系统内存,但是需要小心,多创建几个,每帧循环一次map_nooverwrite,抑制代价高昂丢弃的驱动程序缓冲区重命名。当然,永远不要在读写中做映射,只写,否则你会引入 gpu/cpu 同步并杀死并行性。
最后,如果你想要一个持久的表面并且每帧只有几个 putpixel(或者甚至很多),我会选择一个无序访问视图和一个计算着色器,它消耗一个带有颜色的像素位置缓冲区更新。该缓冲区将再次成为一个没有覆盖映射的动态缓冲区。使用该解决方案,主表面将驻留在显存中。
就个人而言,我什至懒得教 cpu 表面操作,这几乎总是一种糟糕的做法和性能杀手,而不是现代 gpu 架构的方式。这在十年前还不是一个基本的图形概念。