在许多情况下,讨论现代实时渲染技术往往围绕着可编程管线及它可以做些什么。管线的确是实时渲染一个至关重要的部分,特别是图形开发人员的主要任务之一是使用的管线编写着色器程序。然而,在这些讨论中与管线有连接的内存资源往往被忽视。这是同样重要的在理解对于特定的算法需要什么样的资源,在那里被使用,它们将如何被使用。
本章将深度检查Direct3D 11内存资源的主题。我们首先确定Direct3D 11API是如何组织和管理资源的然后主要考虑两种主要的资源类型-缓冲区和纹理,我们将详细的讨论每个子类型资源,它是如何产生的,如何使用它,以及当不再需要它的时候如何被释放。资源使用的讨论还将介绍资源视图的概念,及一种用于将资源连接到管线的特定位置的适配器类型。
任何讨论资源也必须看一下他们使用的两个方面。应用程序是关于创建、填充和连接资源到管线。然而,我们还必须考虑资源在管线中是如何被使用的。在一个可编程着色器中资源如何被声明和使用与正确创建资源一样重要。这个话题将在着色器程序详细讨论来提供一个声音理解这种用法,这将是建立在3 - 7章。
正如我们将在本章后面所看到的,资源在被创建之前关于资源将如何被使用的有一个清晰的理解是非常重要的,使用域是预先确定的新成立以来输入参数。如果不正确配置,资源在您的应用程序中可能有几个负面影响,由于错误从表现不佳一直到完全无法执行管线。这使得资源确实是一个非常重要的话题!
图2.1 Direct3D 11 资源接口继承
2.1资源概述
在Direct3D 11中有两个基本类型的资源:缓冲区和纹理。每个有几个子类型,并且每个子类型都有不同的配置选项。首先对于创建资源可用选项的纯粹数量可能有点压倒性,所以我们讨论的话题将从他们在Direct3D 11API中是如何被组织的开始。通过从一个较高的水平开始,我们可以开始了解不同资源的差异然后依赖这些知识和这些差异的额外细节确定资源怎样被使用。
Direct3D 11资源类结构正如图2.1所示那样被组织。在这里,您可以看到,对于整个API只有四个资源类可供使用-缓冲区,和ID、2 d和3 d纹理。
图表还显示这些资源类派生自一个公共基础类,名为ID3D11Resource。这是有道理的,提供了一个指示一个共同的主题,我们将在本章回顾。 资源是一块依附于管线和用来输入输出的内存块。换句话说资源是一块GPU能使用和操控的内存区域,即使它们有不同的名字和支持不同的概念,它们之间真正的不同之处在于“语义”它们能被绑定到不同的管线阶段和它们格式,权限、和使用规则有所不同。
2.1.1 资源创建
正如在第一章“Direct3D 11概述 ”所描述的ID3D11Device 接口负责创建所有的内存资源。然后被创建的资源直接或者以资源视图的形式依附于管线,然后在管线执行事件的时候在它们所依附的阶段被使用。对于每种资源类型来说资源创建过程使用不同的ID3DllDevice方法,但它们都遵循相同的一般模式。
创建方法都需要三个参数,第一个参数是一个指定了一个资源能被创建的所有各种选项的结构,。它被称为资源描述。每种资源类型使用自己的描述结构,因为他们每个都有一组不同的可用属性,但结构都服务于同样的目的--定义创建资源所需的特征。这些结构在这一章将会详细研究,并且他们适当的配置包含所需资源做你想它去做的事情的大部分工作。资源创建方法的第二个参数是一个指向D3D11_SUBRESOURCE_DATA结构的指针,用于提供加载到一个资源的初始数据。例如,如果一个缓冲资源将保存静态顶点数据,这种结构将用于传递一个模型的顶点数据到缓冲区中。如果其内容不会改变这消除了创建缓冲区后需要手动操作缓冲区的步骤。如果不需要初始化这个参数也可以被设置为null。最后一个参数是一个指向适当资源接口的指针的指针,这是资源创建事成功后创建资源的指针被存储的地方。
在这些方法中,真正的配置出现在资源描述结构。如前所述,每个资源类型都有其自己的结构用于定义
它自己的属性。然而,这有一些所有结构共享的公用元素。这包括使用标志,,绑定标志,CPU访问标志,和其他标志。由于这些参数是所有不同的资源类型公有的,我们在这会详细讨论它们。资源独有的特定类型的参数在本章后面在各自的资源类型的部分讨论。
2.1.1.1资源使用标志(Usage flags)
我们第一个将检查的资源参数,是使用指明。简单的说,该参数用于指定应用程序打算使用资源来做什么。在一般情况下,我们可以考虑资源是在计算机的某个地方的一个内存块。显存和系统内存都可以保存资源,并且资源能在Direct3D 11运行时被复制和传送到每一种内存类型。为了优化资源驻留的位置,以及它是如何由运行时/驱动程序内部处理,应用程序必须使用这种使用参数指定其意图。这不同于以前的Direct3D版本,它允许用户指定将有资源驻留的内存池。然而,通过指示资源的使用意图,类似控制的等级被提出。可用值的列表由D3D11_USAGE枚举封装,这如表2.1所示。
typedef enum D3D11_USAGE { D3D11_USAGE_DEFAULT = 0, D3D11_USAGE_IMMUTABLE = 1, D3D11_USAGE_DYNAMIC = 2, D3D11_USAGE_STAGING = 3 } D3D11_USAGE;
列表 2.1 D3D11_USAGE 枚举
typedef enum D3D11_CPU_ACCESS_FLAG
{ D3D11_CPU_ACCESS_WRITE = 0x10000L, D3D11_CPU_ACCESS_READ = 0x20000L } D3D11_CPU_ACCESS_FLAG;
我们可以使用OR来指明是否资源被读或写。如
D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ .但是根据此表
typedef enum D3D11_BIND_FLAG { D3D11_BIND_VERTEX_BUFFER = 0x1L, D3D11_BIND_INDEX_BUFFER = 0x2L, D3D11_BIND_CONSTANT_BUFFER = 0x4L, D3D11_BIND_SHADER_RESOURCE = 0x8L, D3D11_BIND_STREAM_OUTPUT = 0x10L, D3D11_BIND_RENDER_TARGET = 0x20L, D3D11_BIND_DEPTH_STENCIL = 0x40L, D3D11_BIND_UNORDERED_ACCESS = 0x80L, D3D11_BIND_DECODER = 0x200L, D3D11_BIND_VIDEO_ENCODER = 0x400L } D3D11_BIND_FLAG;
typedef enum D3D11_RESOURCE_MISC_FLAG { D3D11_RESOURCE_MISC_GENERATE_MIPS = 0x1L, D3D11_RESOURCE_MISC_SHARED = 0x2L, D3D11_RESOURCE_MISC_TEXTURECUBE = 0x4L, D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS = 0x10L, D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS = 0x20L, D3D11_RESOURCE_MISC_BUFFER_STRUCTURED = 0x40L, D3D11_RESOURCE_MISC_RESOURCE_CLAMP = 0x80L, D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX = 0x100L, D3D11_RESOURCE_MISC_GDI_COMPATIBLE = 0x200L, D3D11_RESOURCE_MISC_SHARED_NTHANDLE = 0x800L, D3D11_RESOURCE_MISC_RESTRICTED_CONTENT = 0x1000L, D3D11_RESOURCE_MISC_RESTRICT_SHARED_RESOURCE = 0x2000L, D3D11_RESOURCE_MISC_RESTRICT_SHARED_RESOURCE_DRIVER = 0x4000L, D3D11_RESOURCE_MISC_GUARDED = 0x8000L, D3D11_RESOURCE_MISC_TILE_POOL = 0x20000L, D3D11_RESOURCE_MISC_TILED = 0x40000L, D3D11_RESOURCE_MISC_HW_PROTECTED = 0x80000L } D3D11_RESOURCE_MISC_FLAG;
D3D11_RESOURCE_MISC_SHARED标识资源能在多个ID3DllDevice实例中共享。D3D11_RESOURCE_MISC_GDI_COMPATIBLE标识了一个资源能用来和GDI交互。