R700指令集架构参考手册——第二章:程序组织和状态

来源:互联网 发布:数据挖掘笔试题 编辑:程序博客网 时间:2024/05/26 02:55

R700程序由控制流(CF)、ALU(译者注:算术逻辑单元)、取纹理和取顶点指令组成。ALU可以具有多达三个源操作数和一个目的操作数。指令对32位或64位IEEE浮点值以及带符号或无符号整型进行操作。某些指令的执行致使断言(predicate)位被写,从而影响后面的指令。图形程序一般使用取顶点和取纹理指令来加载数据;而通用计算应用一般使用取纹理指令来加载数据。

 

2.1 程序类型

 

 

以下程序类型一般运行在R700上(见图1.2):

1、顶点着色器(VS)——读顶点,处理它们。依赖于是否有一个几何着色器(GS)在活动,它要么对一个VS环缓存,要么对一个参数Cache和位置缓存输出结果。它不引入新的图元。一个顶点着色器可以调用一个取子例程(FS,Fetch Subroutine),它是一个特殊的全局程序用于取顶点数据,出于执行目的,作为顶点程序的一部分。FS提供了在被一个VS所要求的取数据的过程和VS其本身之间的驱动独立性。

2、几何着色器(GS)——从VS环缓存读取图元,并且为每个输入图元,写一个或多个图元作为输出到GS环缓存。这个程序类型是可选的;当活动的时候,它要求一个DMA拷贝(DC)程序处于活动。GS从由VS所创建的片外存储器缓存读多达6个顶点;它输出一变量个数的图元到一第二个存储器缓存。

3、DMA拷贝(DC)——从GS环缓存到参数Cache和位置缓存传输数据。它对于正在运行一个几何着色器的系统而言是所必要的。

4、像素着色器(PS)或片段着色器——这类程序:

    ——接收来自将被着色的光栅化器的像素数据

    ——处理四像素集(以一个2×2阵列所安排的四个像素元素),并且

    ——写输出到多达8个本地存储器缓存,称为多重渲染目标(MRT,Multiple Render Target),一个MRT可以包含一个或多个帧缓存。

5、计算着色器(CS)——一个通用程序,使用其线程ID作为一个索引来执行:

    ——收集对一组或多组输入数据的读

    ——算术计算,以及

    ——对一组或多组输出数据离散写到存储器

 

所有程序类型接受相同指令类型,并且所有程序类型可以运行在支持这些程序的任一可用的DPP阵列流水线;然而,每个内核类型有某些限制,这将会根据具体的类型进行描述。

 

2.1.1 数据流

 

主机可以初始化R700以一个或两个配置运行——带有或不带有一个几何着色器程序和一个DMA拷贝程序。见图1.2。每种数据流在以下部分描述。

 

2.1.2 不存在几何程序

 

这个处理配置由以下步骤组成:

1、VS程序发送一个指向本地存储器的一个缓存,包含多达64个顶点索引。

2、R700硬件将其输入缓存(远程存储器)中的这些顶点组织成向量。(译者注:可以想像glDrawArray这类OpenGL函数,硬件根据输入的绘制模式类型,比如GL_LINE、GL_TRIANGLE_STRIP等将顶点组织成向量)

3、当所有顶点准备好被处理时,R700分配GPR以及线程空间用于处理64个顶点的每一个,基于编译器提供的大小。

4、VS程序调用取子例程(FS)程序,将顶点数据取到GPR中,并将控制返回给VS程序。

5、变换、光照、以及VS程序的其它部分运行。

6、VS程序在位置缓存中分配空间,并输出顶点位置(XYZW)。

7、VS程序分配参数Cache和位置缓存空间,并输出每个顶点的位置和参数。

8、VS程序退出,R700释放其GPR空间。

9、当VS程序完成时,像素着色器(PS)程序开始。

10、R700硬件从位置缓存中的数据和顶点几何翻译器(VGT)中的数据汇编图元,执行扫描转换和最后的像素插值,并将这些值加载到GPR中。

11、PS程序然后为每个像素运行。

12、程序将数据输出到一个帧缓存,然后R700释放起GPR空间。

 

2.1.3 几何着色器存在

 

表2.2展示了当一个几何程序存在时,程序运行的次序。

这个处理配置由以下步骤组成。

1、R700硬件从顶点几何翻译器(VGT)将输入索引或图元以及顶点ID加载到GPR中。

2、VS程序取顶点(译者注:单数)或所需要的顶点(译者注:复数)。

3、变换、光照和VS程序的其它部分运行。

4、VS程序通过写顶点输出到VS环缓存结束。

5、GS程序从VS环缓存读多个顶点,执行其几何功能,并且针对每个输入顶点输出一个或多个顶点到GS环缓存。VS程序对每个输入只能写一单个顶点;GS程序对于每个输入可以写大量的顶点。每次一个GS程序输出一个顶点时,它对顶点VGT指示,一个新的顶点已经被输出(使用EMIT_*指令)。VGT计数由每个GS程序所创建的顶点个数的总和。GS程序通过发布CUT_VERTEX指令划分图元条带(primitive strip)。

6、当所有顶点已被输出时GS程序结束。没有位置和参数被输出。

7、DC程序从GS环缓存读取顶点数据,并使用一条MEM_*存储器输出指令将此数据传输到参数Cache和位置缓存。

8、DC程序退出,R700释放GPR空间。

9、PS程序运行。

10、R700从位置缓存、参数Cache和VGT中的数据汇编图元。

11、硬件执行扫描转换以及最后的像素插值,并且硬件将这些值加载到GPR中。

12、PS程序运行

13、当PS程序到达数据末尾时,它使用EXPORT指令将数据输出到一个帧缓存或其它渲染目标(多达8个)。

14、程序通过执行一条EXPORT_DONE指令退出,并且处理器释放GPR空间。

 

2.2 指令术语

 

表2.3概括了本文档所用到的某些指令相关的术语。指令其本身在剩下的章节中描述。每条指令的细节在第9章中给出。寄存器类型在“寄存器”中描述。

 

1、微代码格式——32位。对于所有指令的一种或若干中编码格式。它们在3.1、4.1、5.1、6.1小节以及第10章中描述。

2、指令——64或128位。两个到四个微代码格式,以指定:

    (1)控制流(CF)指令(64位)。这些包括:通用控制流指令(诸如分支和循环),分配缓存空间和输出数据的指令,以及启动ALU、取纹理、或取顶点子句(Clause)的执行的指令。

    (2)ALU指令(64位)

    (3)取纹理指令(128位)

    (4)取顶点指令(128位)

    (5)数据共享指令(128位)

    (6)存储器读指令(128位)

指令在微代码格式中通过它们的域名和助记符中的_INST_字符串进行标识。指令的功能在第9章中描述。

3、ALU指令组——64到448位。可变大小的指令和常量组,由以下构成:

    (1)一到五个ALU指令

    (2)零到两个64位字面常量

ALU指令组在4.3小节中描述

4、字面常量——64位。字面常量指定了两个32位值,它们可以表示与一个128位向量的两个元素相关联的值。这些常量可选地可以包含在ALU指令组中。

字面常量在4.3小节中描述。

5、槽(Slot)——64位。在一个ALU指令组内一个有序的位置。每个ALU指令组有1到7个槽,相应与ALU指令组中的ALU指令与字面常量的号码。

槽在4.3小节中描述

6、子句(Clause)——64到64x128位(64个128位字)。一组相同类型的指令。子句的类型有:

    (1)ALU子句(包含ALU指令组)

    (2)取纹理子句

    (3)取顶点子句

子句由控制流(CF)指令启动,并在2.3小节中描述

7、输出(Export)——做下列任意一件事:

    (1)从GPR写数据到输出缓存(一个“临时缓存(scratch buffer)”,“帧缓存”,“环缓存”,“流缓存”,或“缩减(reduction)缓存”)。

    (2)将一个数据输入的地址写到存储器控制器。

    (3)从一个输入缓存(“临时缓存”或“环缓存”)读取数据到GPR。

7、取(Fetch)——使用一个取顶点或取纹理指令子句加载数据。加载对于通用目的寄存器(GPR)不是必须的;加载的指定类型可能受限于存储目的的指定类型。

8、顶点——一组(x, y)2D坐标。

9、四元(Quad)——安排为一个2乘2阵列的四个(x, y)数据元素。

10、图元(Primitive)——一个光栅化之前的点、线段或多边形。它具有由几何坐标指定的顶点。通过跨图元的线性插值,顶点可以与额外的数据相关联。

11、片断(Fragment)——对于图形编程:

    (1)光栅化一个图元的结果。一个片断没有顶点;取而代之的是它由(x, y)坐标表示。

                                         对于通用目的编程:

    (1)一组(x, y)数据元素

12、像素(Pixel)——对于图形编程:

    (1)将一个片断放置在一个(x, y)帧缓存中的结果。

                                 对于通用目的编程:

    (1)一组(x, y)数据元素

 

2.3 控制流和子句

 

每个程序由两个部分组成:

1、控制流——控制流指令可以:

    ——启动ALU、取纹理、或取顶点指令的执行。

    ——输出数据到一个缓存。

    ——控制分支、循环和栈操作。

2、子句——一组同构指令;每个子句独立地,由ALU、取纹理、取顶点、本地数据共享、或存储器读指令组成。启动一个ALU、取纹理、或取顶点子句的一条控制流指令通过引用一个合适的子句执行。

 

表2.4提供了一个典型的程序流例子

 

            功能                                                                                               微代码格式

                                                                            控制流(CF)代码                                     子句代码

 

启动循环                                                                CF_DWORD[0, 1]

 

启动取纹理子句                                                       CF_DWORD[0, 1]

 

取纹理或取顶点子句,以从存储器将数据加载到GPR                                                                   TEX_DWORD[0, 1, 2]

 

启动ALU子句                                                        CF_ALU_DWORD[0, 1]

 

ALU子句在已被加载的数据和字面常量上计算。                                                                         ALU_DWORD[0, 1]

这个例子展示了由一单个包含五条ALU指令                                                                               ALU_DWORD[0, 1]

(每条两个四字)以及两个四字的字面常量的                                                                            ALU_DWORD[0, 1]

ALU指令组所构成的一单个子句(译者注:                                                                               ALU_DWORD[0, 1]

这里,一个字为16位)                                                                                                    ALU_DWORD[0, 1]  最后一位,置1

                                                                                                                                        Literal[X, Y]

                                                                                                                                        Literal[Z, W]

 

结束循环                                                                CF_DWORD[0, 1]

 

在一个输出缓存中分配空间                                    CF_ALLOC_EXPORT_DWORD0

                                                                        CF_ALLOC_EXPORT_DWORD1_BUFFER

 

将结果从GPR输出(写)到输出缓存                        CF_ALLOC_EXPORT_DWORD0

                                                                        CF_ALLOC_EXPORT_DWORD1_BUFFER

 

 

控制流指令(译者注:复数):

 

1、构成主程序。分支语句、循环以及子例程调用在程序的控制流部分中被直接表达。

2、包含同步操作的机制。

3、指示一个子句什么时候完成时。

4、对于缓存而言是所要求的,在程序块的输出缓存中分配缓存,以及写到一个程序块的输出缓存。

 

一些程序类型(VS、GS、DC、PS)具有与其它块同步的控制流指令。

每个子句被一条控制流指令调用,是一有限长度指令的顺序列表。子句不包含控制流语句,但ALU子句指令可以基于每条指令应用一个断言。在一单个子句内的指令串行执行。一个程序的多个子句可以并行执行,如果它们包含不同类型的指令,并且子句相互独立(这种并行执行对程序员是不可见的,除了性能提升)。

ALU子句包含以每5个ALU(ALU.[X, Y, Z, W]和ALU.Trans)执行操作的指令,包括设置和使用断言,以及像素扼杀(pixel kill)操作(见4.8.1小节)。取纹理子句包含执行纹理以及从存储器读取常量的指令。取顶点子句专用于从存储器获取顶点数据。缺乏一个顶点Cache的系统可以在一个纹理子句中执行取顶点操作。

 

一个断言(predicate)是一个比特,它可以被置1或清0,作为计算某些条件的结果;从而,它被用来屏蔽写一个ALU的结果或本身作为一个条件。有两种断言,每种都在一个ALU子句中被置1:

1、第一种对于ALU子句本身而言,是一单个本地断言。一旦被计算,断言可以在后面的一条指令中被引用,以带条件地将一个ALU计算结果写到所指示的通用目的寄存器。

2、第二种类型是一个断言栈中的一个比特。一个ALU子句在栈中计算断言位,并对栈进行操作。在栈中的一个断言位可以在一条控制流指令中被引用,以引起带条件的分支。

 

 

2.4 指令类型和分组

 

R700家族设备识别以下指令类型:

1、控制流指令

2、子句类型:ALU、取纹理、取顶点、本地数据共享子句,以及存储器读子句

 

在处理器中对于每种指令类型有独立的指令Cache。

 

一个CF程序没有最大大小;然而,每个子句有一个最大大小。当一个程序在存储器中被组织时,指令必须如下安排:

1、所有CF指令

2、所有ALU子句

3、所有取纹理和取顶点子句

4、所有本地数据共享子句

5、所有读存储器子句

 

CPU主机在执行一个程序前,配置每个程序类型的基地址。

 

2.5 程序状态

 

2.6 数据共享