【原创】Linux环境下的图形系统和AMD R600显卡编程(6)——AMD显卡GPU命令格式

  前面一篇blog里面描述了命令环缓冲区机制,在命令环机制下,驱动写入PM4(不知道为何会取这样一个名字)包格式的命令对显卡进行配置。这一篇blog将详细介绍命令包的格式。

  当前定义了4中命令包,分别是0型/1型/2型和3型命令包,命令包由两部分组成,第一部分是命令包头,第二部分是命令包主体,命令包头为请求GPU执行的具体操作,命令主体为执行该操作需要的数据。

  • 0型命令包

  0型命令包用于写连续N个寄存器。包主体部分是依次往这些寄存器写的值。包头各个部分的意义为:

域名称 描述
12:0 BASE_INDEX 要写的连续寄存器的第一个寄存器地址,最大地址0x7FFF
14:13 保留位  
15 ONE_REG_WR
0表示将包主体的数据依次写入寄存器中

1表示所有数据写入同一个寄存器

29:16 COUNT 要写的寄存器数目N-1
31:30 TYPE 包类型,0型命令包类型名为0

  Linux内核代码./drivers/gpu/drm/radeon/r600.c r600\_fence\_ring\_emit函数有如下语句:

  radeon_ring_write(rdev, PACKET0(CP_INT_STATUS, 0));

  radeon_ring_write(rdev, RB_INT_STAT);

  PACKET0定义如下:

    #define PACKET0(reg, n) ((PACKET_TYPE0 << 30) |  \     包类型 0型命令包

(((reg) >> 2) & 0xFFFF) |          \        寄存器偏移基地址

((n) & 0x3FFF) << 16)                     要写的寄存器数目

  所有类型的数据包31~30bit为包类型标识符,0型数据包的类型标识符为0,其30bit为PACKET_TYPE0(0x0),29~16bit为命令写的寄存器数量-1((n) & 0x3FFF) << 16),上面例子只写一个寄存器,其值为0。第14~132bit为保留位,12~0bit ((reg) >> 2) & 0xFFFF)为第一个寄存器偏移地址,由于使用0型包可以访问的所有寄存器都是4字节的,寄存器地址都是4字节对其的,所以低2位为0。

  • 1型命令包

  1型命令包用于写两个的寄存器,1型命令包包头定义如下:

域名称 描述
10:0 REG_INDEX1 第一个寄存器的地址
22:11 REG_INDEX2 第二个寄存器的地址
29:22 RESERVED 保留位
31:30 TYPE 1型命令包的类型为0x1

  由于1型命令包可以用0型命令包代替而且1型命令包并不能够访问到所有寄存器,在内核radeon驱动中并没有使用1型命令包。

  • 2型命令包

  2型命令包是一个空命令包,用于填充对齐命令。2型命令包没有包主体,其包头最高两位为0x2,其它位无意义。

  2型命令包不做任何操作,仅用于填充保证对齐用,填充ring buffer的时候有对齐要求,内核radeon驱动对齐要求是16个dword(16×4字节),在命令没有16 dword对齐的时候,就需要使用2型命令包填充。

  drivers/gpu/drm/radeon/radeon_ring.c radeon_ring_commit函数用于通知GPU从ring buffer中取数据并执行,该函数包含如下代码:

count_dw_pad = (rdev->cp.align_mask + 1) - (rdev->cp.wptr & rdev->cp.align_mask);

for (i = 0; i < count_dw_pad; i++) {

radeon_ring_write(rdev, 2 << 30);

}

  第一句用于计算对齐命令需要的dword数目,后面的for循环用于填充2型命令。2型命令仅有个命令头部,并且只有31~30bit有效。

  • 3型命令包

  3型命令包是最功能最丰富的包,图形的主要功能都是通过这类包实现的。3型命令包主体内容由包头的IT_OPCODE决定。

域名称 描述
7:0 reserved 保留位
15:8 IT_OPCODE 操作码
29:16 COUNT 包主题DWORDS数目-1
31:30 TYPE 3型包类型为0x3

  3型命令是主要的命令包,涵盖了寄存器设置/绘图命令/同步等主要操作。以下是一个使用3型命令包设置寄存器的例子,这段代码来自drivers/gpu/drm/radeon/r600.c 的r600_ib_test函数:

ib->ptr[0] = PACKET3(PACKET3_SET_CONFIG_REG, 1);

ib->ptr[1] = ((scratch - PACKET3_SET_CONFIG_REG_OFFSET) >> 2);

ib->ptr[2] = 0xDEADBEEF;

ib->ptr[3] = PACKET2(0);

ib->ptr[4] = PACKET2(0);

......

ib->ptr[15] = PACKET2(0);

ib->length_dw = 16;

  这段代码使用了indirect buffer,但是填充的命令和ring buffer中填充的命令是一样的。

#define PACKET3(op, n)  ((PACKET_TYPE3 << 30) |             \

(((op) & 0xFF) << 8) |             \

((n) & 0x3FFF) << 16)

  3型命令头部包含了操作码op和数据数目(以dword计)。上面例子中PACKET3(PACKET3_SET_CONFIG_REG, 1) PACKET3_SET_CONFIG_REG表明这次命令包用于设置寄存器,1表明后面有2个dword数据,分别是(scratch - PACKET3_SET_CONFIG_REG_OFFSET) >> 2(寄存器地址)和0xDEADBEEF(往寄存器中写的值)。后面是用于对齐的2型包。

  下面使用一个更加复杂的命令包来说明3型包的使用,下面的这个命令包用于执行一个简单的2D操作。r600显卡是ATI推出的第一款使用统一着色器的GPU,r600及其以后的显卡不包含单独的2D单元,而是使用3D部件执行2D操作。为了简单起见,这里我们使用r500显卡上的填充矩形的命令包。

radeon_ring_write(rdev, PACKET3(PACKET3_PAINT_MULTI, 6));

radeon_ring_write(rdev,

RADEON_GMC_DST_PITCH_OFFSET_CNTL |

RADEON_GMC_DST_CLIPPING | // important

RADEON_GMC_BRUSH_SOLID_COLOR |          // 13 << 4

(RADEON_COLOR_FORMAT_ARGB8888 << 8) |     // << 8

RADEON_GMC_SRC_DATATYPE_COLOR |         // 4 << 12

RADEON_ROP3_P |                              // << 16

RADEON_GMC_CLR_CMP_CNTL_DIS);           // 1 << 28

radeon_ring_write(rdev, ((pitch / 64) << 22) | (fb_offset>>10));

radeon_ring_write(rdev, 0 | (0 << 16));                                   // SC_TOP_LEFT

radeon_ring_write(rdev, (fb_w -1) | ((fb_h -1) << 16));    // SC_BOT_RITE

radeon_ring_write(rdev, color); // this is color

radeon_ring_write(rdev, (x << 16) | y);

radeon_ring_write(rdev, (w << 16) | h);

radeon_ring_write(rdev, PACKET0(RADEON_DSTCACHE_CTLSTAT, 0));

radeon_ring_write(rdev, RADEON_RB2D_DC_FLUSH_ALL);

radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0));

radeon_ring_write(rdev, RADEON_WAIT_2D_IDLECLEAN|

RADEON_WAIT_HOST_IDLECLEAN|

RADEON_WAIT_DMA_GUI_IDLE);

  3型包根据他们IT_OPCODE的不同,其IT_BODY差别很大,如果IT_OPCODE的最高位为1(通常是2D绘图命令),那么PACKET还需要加入GUI control。R500上的2D绘图命令有如下格式:

HEADER

GUI_CONTROL

SETUP_BODY

DATA_BLOCK

  其中Header部分对应3型命令包的头,GUI_CONTROL和SETUP_BODY共同构成了当前绘图环境的配置,这两部分加上DATA_BLOCK共同构成了3型包的IT_BODY部分。上面的代码第一句表明该命令包执行的是矩形绘制(PAINT_MULTI可以同时绘制多个矩形,这里我们只绘制了一个矩形)。第二句对应GUI_CONTROL,GUI_CONTROL为32bit,内容为当前绘制环境的标志,下表给出了代码中使用的一些标志(如果是blit操作,除了表中的DSTxx参数外,还需要设置对应的SRCxx参数),关于这些标志更详细的信息可以参考“R5xx Acceleration v1.5.pdf”35-36页相关内容。

域名称 描述
1 DST_PITCH_OFFSET 绘图目标区域的PITCH值和该区域在GPU虚拟地址空间中的偏移,如果该为被置为1,则需要在SETUP_BODY中指定该参数
3 DST_CLIPPING 设置绘图区域的裁剪参数,如果该位置为1,则需要在SETUP_BODY中设置SC_TOP_LEFT和SC_BOTTOM_RIGHT参数
7:4 BRUSH_TYPE 绘图时使用的brush类型,brush类型需要根据这里给出的类型在SETUP_BODY中填brush包,不同的BRUSH_TYPE对应的brush包不同
11:8 DST_TYPE
绘图目标区域的像素类型:

1 :- (reserved)

2 :- 8 bpp pseudocolor

3 :- 16 bpp aRGB 1555

4 :- 16 bpp RGB 565

5 :- reserved

6 :- 32 bpp aRGB 8888

7 :- 8 bpp RGB 332

8 :- Y8 greyscale

9 :- RGB8 greyscale (8 bit intensity, duplicated for all 3 channels. Green channel is used on writes)

10 :- (reserved)

11 :- YUV 422 packed (VYUY)

12 :- YUV 422 packed (YVYU)

13 :- (reserved)

在上面示例程序中,以上标志位均被设置,并且BRUSH\_TYPE被设置为14,DST_TYPE设为32位真彩色。

根据GUI_CONTROL的设置,SETUP_BODY中需要设置以下参数:

DST_PITCH_OFFSET

SC_TOP_LEFT

SC_BOTTOM_RIGHT

BRUSH_PACKET

上面代码中的3-6行即是对这些参数的设置。更多参数的可以参考“R5xx Acceleration v1.5.pdf”37页的内容。

下面对这些参数进行介绍:

  • DST_PITCH_OFFSET

  包括了三部分,31:30位是和tiling相关的标志位,29:22位是以64字节为单位的pitch值,21:0位是DST绘图区域(在xorg中称为pixmap)以1KB为单位在显存中的偏移,这里提示我们,在分配内存的时候必须是1K对齐的,否则在使用的时候会出问题,后面讨论directfb的时候将会碰到这个问题。对于这个参数,上面代码填的是

radeon_ring_write(rdev, ((pitch / 64) << 22) | (fb_offset>>10));

  • SC_TOP_LEFTSC_BOTTOM_RIGHT

  指定绘图区域的裁剪区域,裁剪区域是个矩形,SC_TOP_LEFT指定裁剪区域左上方坐标,2D绘图时以屏幕左上方的点为原点,从左往又为X轴正方向,从上往下为Y轴正方向。

radeon_ring_write(rdev, 0 | (0 << 16));                            // SC_TOP_LEFT

radeon_ring_write(rdev, (fb_w -1) | ((fb_h -1) << 16)); // SC_BOTTOM_RIGHT

  fb_w和fb_h为当前绘图区域的长和宽,这里我们指定的裁剪区域就是整个绘图区域。

  • BRUSH_PACKET

  在GUI_CONTROL中指定的brush type为RADEON_GMC_BRUSH_SOLID_COLOR,关于brush type 和对应的值请参考“R5xx Acceleration v1.5.pdf”38页的内容,这里指定的类型为13,对应的BRUSH\_PACKET格式为4字节,内容为绘图使用的前景色。

radeon_ring_write(rdev, color); // the foreground color

  后面两句代码是DATA_BLOCK部分,对应绘图使用的参数。

radeon_ring_write(rdev, (x << 16) | y);// 矩形左上角坐标

radeon_ring_write(rdev, (w << 16) | h);// 矩形宽和高

  PAINT_MULTI命令包的DATA_BLOCK部分定义如下表示:

顺序 域名称 描述
1 [DST_X1 | DST_Y1] 第1个矩形左上角的坐标,高16位为X轴坐标,低16位为Y轴坐标
2 [DST_W1 | DST_H1] 第1个矩形的宽和高
...    
2n-1 [DST_Xn | DST_Yn] 第n个矩形左上角的坐标
2n [DST_Wn | DST_Hn] 第n个矩形的宽和高

  

  下面给出了一些代码,读者根据前面的介绍并参考“R5xx Acceleration v1.5.pdf” 是很容易理解的,如果机器上有R500核心的显卡,将这些代码添加到drivers/gpu/drm/radeon/radeon_test.c文件中并调用这些函数,在开启radeon_testing的情况下就能在启动阶段看到效果。

  • 画线

  POLYLINE的op_code为0x95,用于绘制折线。

1 void r5xx_draw_line_2d(struct radeon_device *rdev, uint64_t fb_location,

2             int *points, int num ,int color, int fb_w, int fb_h)

3 {

4     int r;

5     struct radeon_fence *fence = NULL;

6     int ndw = 32 + 6 + num;// ?? 32 is enough

7     int i = 0;

8

9     r = radeon_fence_create(rdev, &fence);

10     if (r) {

11         DRM_ERROR("Failed to create fence\n");

12         goto out_cleanup;

13     }

14     r = radeon_ring_lock(rdev, ndw);

15     radeon_ring_write(rdev, PACKET3(PACKET3_POLYLINE, 4 + num));

16     radeon_ring_write(rdev,

17             RADEON_GMC_DST_PITCH_OFFSET_CNTL |

18             RADEON_GMC_DST_CLIPPING | // important

19             RADEON_GMC_BRUSH_SOLID_COLOR |        // 13 << 4

20             (RADEON_COLOR_FORMAT_ARGB8888 << 8) |   //  << 8

21             RADEON_GMC_SRC_DATATYPE_COLOR |      // ??  4 << 12

22             RADEON_ROP3_P |                      // << 16

23             RADEON_GMC_CLR_CMP_CNTL_DIS);

24     radeon_ring_write(rdev, ((fb_w * 4 / 64) << 22) | (fb_location >>10));

25     radeon_ring_write(rdev, 0 | (0 << 16));

26     radeon_ring_write(rdev, (fb_w -1) | ((fb_h -1) << 16));

27     radeon_ring_write(rdev, color);

28     for( i = 0; i < num; ++i){

29            radeon_ring_write(rdev, *points++);

30     }

31     radeon_ring_write(rdev, PACKET0(RADEON_DSTCACHE_CTLSTAT, 0));

32     radeon_ring_write(rdev, RADEON_RB2D_DC_FLUSH_ALL);

33     radeon_ring_write(rdev,

34             RADEON_WAIT_2D_IDLECLEAN |

35             RADEON_WAIT_HOST_IDLECLEAN |

36             RADEON_WAIT_DMA_GUI_IDLE);

37

38     if(fence) {

39         r = radeon_fence_emit(rdev, fence);

40     }

41     radeon_ring_unlock_commit(rdev);

42     r = radeon_fence_wait(fence, false);

43     if (r) {

44         DRM_ERROR("Failed to wait for fence\n");

45         goto out_cleanup;

46     }

47

48 out_cleanup:

49     if(fence) {

50         radeon_fence_unref(&fence);

51     }

52 }

  注意到这里调用了三个函数处理fence:radeon_fence_create,创建一个fence;radeon_fence_emit,在提交ring buffer之前发送fence;radeon_fence_wait,等待fence。在下一篇blog“中断机制”中会介绍。

  •  画矩形

  使用PAINT_MULTI可以绘制矩形,可以在一次命令中绘制多个矩形,其IT_OPCODE为0x9a。

1 void r5xx_draw_rectangl_2d(struct radeon_device *rdev, uint64_t fb_location,

2                 int x, int y, int w, int h, int color, int fb_w, int fb_h)

3 {

4     int r;

5     int ndw = 32 + 6;// ?? 32 is enough

6     struct radeon_fence *fence = NULL;

7

8     r = radeon_fence_create(rdev, &fence);

......

13     r = radeon_ring_lock(rdev, ndw);

......

18     radeon_ring_write(rdev, PACKET3(PACKET3_PAINT_MULTI, 6));

19     radeon_ring_write(rdev,

20             RADEON_GMC_DST_PITCH_OFFSET_CNTL |

21             RADEON_GMC_DST_CLIPPING | // important

22             RADEON_GMC_BRUSH_SOLID_COLOR |        // 13 << 4

23             (RADEON_COLOR_FORMAT_ARGB8888 << 8) |   //  << 8

24             RADEON_GMC_SRC_DATATYPE_COLOR |      // ??  4 << 12

25             RADEON_ROP3_P |                      // << 16

26             RADEON_GMC_CLR_CMP_CNTL_DIS);          // 1 << 28

27

28     radeon_ring_write(rdev, ((fb_w * 4 / 64) << 22) | (fb_location >>10));

29     radeon_ring_write(rdev, 0 | (0 << 16));

30     radeon_ring_write(rdev, (fb_w -1) | ((fb_h -1) << 16));

31

32     radeon_ring_write(rdev, color); // this is color

33     radeon_ring_write(rdev, (x << 16) | y);

34     radeon_ring_write(rdev, (w << 16) | h);

35

36     radeon_ring_write(rdev, PACKET0(RADEON_DSTCACHE_CTLSTAT, 0));

37     radeon_ring_write(rdev, RADEON_RB2D_DC_FLUSH_ALL);

38     radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0));

39     radeon_ring_write(rdev,

40           RADEON_WAIT_2D_IDLECLEAN |

41           RADEON_WAIT_HOST_IDLECLEAN |

42           RADEON_WAIT_DMA_GUI_IDLE);

43

44     r = radeon_fence_emit(rdev, fence);

......

49     radeon_ring_unlock_commit(rdev);

50     r = radeon_fence_wait(fence, false);

......

55 out_cleanup:

......

59 }

  • BLT

1 void r6xx_blit_2d(struct radeon_device *rdev,

2             uint64_t src_ad, uint64_t dst_addr,

3             int src_x, int src_y, int dst_x, int dst_y,

4             int src_w, int src_h, int fb_w, int fb_h)

5 {

6     int r;

7     int ndw;

8     struct radeon_fence *fence = NULL;

9     ndw = 64 + 10;

10

......

21     radeon_ring_write(rdev, PACKET3(PACKET3_BITBLT_MULTI, 8));

22     radeon_ring_write(rdev,

23                 RADEON_GMC_SRC_PITCH_OFFSET_CNTL |

24                 RADEON_GMC_DST_PITCH_OFFSET_CNTL |

25                 RADEON_GMC_SRC_CLIPPING |

26                 RADEON_GMC_DST_CLIPPING |

27                 RADEON_GMC_BRUSH_NONE |

28                 (RADEON_COLOR_FORMAT_ARGB8888 << 8) |

29                 RADEON_GMC_SRC_DATATYPE_COLOR |

30                 RADEON_ROP3_S |

31                 RADEON_DP_SRC_SOURCE_MEMORY |

32                 RADEON_GMC_CLR_CMP_CNTL_DIS |

33                 RADEON_GMC_WR_MSK_DIS);

34 // SRC_PITCH_OFFSET

35     radeon_ring_write(rdev, ((fb_w * 4/64) << 22) | (src_addr >> 10));

36 // DST_PITCH_OFFSET

37     radeon_ring_write(rdev, ((fb_w * 4/64) << 22) | (dst_addr >> 10));

38 // SRC_SC_BOT_RITE

39 //  radeon_ring_write(rdev, (0x1fff) | (0x1fff << 16));

40     radeon_ring_write(rdev, (fb_w -1) | ((fb_h -1) << 16));

41 // SC_TOP_LEFT

42     radeon_ring_write(rdev, 0 | (0 << 16));

43 // SC_BOT_RITE

44 //  radeon_ring_write(rdev, (0x1fff) | (0x1fff << 16));

45     radeon_ring_write(rdev, (fb_w -1) | ((fb_h -1) << 16));

46 // [SRC_X1 | SRC_Y1]

47     radeon_ring_write(rdev, (src_x << 16) | src_y);

48 // [DST_X1 | DST_Y1]

49     radeon_ring_write(rdev, (dst_x << 16) | dst_y);

50 // [SRC_W1 | SRC_H1]

51     radeon_ring_write(rdev, (src_w << 16) | src_h);

......

}

参考资料:

  本节内容主要参考资料为“R5xx Acceleration v1.5.pdf”。

时间: 2024-08-04 12:21:02

【原创】Linux环境下的图形系统和AMD R600显卡编程(6)——AMD显卡GPU命令格式的相关文章

Linux环境下的图形系统和AMD R600显卡编程(1)——Linux环境下的图形系统简介

转:https://www.cnblogs.com/shoemaker/p/linux_graphics01.html Linux/Unix环境下最早的图形系统是Xorg图形系统,Xorg图形系统通过扩展的方式以适应显卡和桌面图形发展的需要,然而随着软硬件的发展,特别是嵌入式系统的发展,Xorg显得庞大而落后.开源社区开发开发了一些新的图形系统,比如Wayland图形系统. 由于图形系统.3D图形本身的复杂以及历史原因,Linux下的图形系统相关的源码庞大而且复杂,而且缺少学习的资料(所有源代码

【原创】Linux环境下的图形系统和AMD R600显卡编程(5)——AMD显卡显命令处理机制

通常通过读写设备寄存器对设备进行编程,在X86系统上,有专门的IO指令进行编程,在其他诸如MIPS.SPARC这类系统上,通过将设备的寄存器映射到内存地址空间直接使用读写内存的方式对设备进行编程. Radeon显卡提供两种方式对硬件进行编程,一种称为“推模式”(push mode)即直接写寄存器的方式,另一种称为拉模式,这篇blog讨论拉模式,这也是驱动中使用的模式. 在拉模式下,驱动使用命令流(Command Stream)的形式进行对显卡编程:驱动程序将需要对显卡进行配置的一连串命令写入命令

【原创】Linux环境下的图形系统和AMD R600显卡编程(9)——R600显卡的3D引擎和图形流水线

1. R600 3D引擎 R600核心是AMD一款非常重要的GPU核心,这个核心引入了统一处理器架构,其寄存器和指令集同以前的GPU 都完全不同,对其编程也有比较大的区别. 图1显示了R600 GPU 核心的硬件逻辑图,R600 GPU 包含并行数据处理阵列(DPP array).命令处理器.内存控制器以及其他逻辑部件,R600的命令处理器读取驱动编写命令并解析命令,R600还要将硬件产生的“软中断”发送给CPU.R600的内存控制器能够访问R600 GPU核上的所有内存(VRAM内存,或者称本

【原创】Linux环境下的图形系统和AMD R600显卡编程(10)——R600显卡的3D引擎编程

3D图形处理流水线需要流经多个硬件单元才能得到最后的渲染结果,流水线上的所有的硬件单元必须被正确编程,才能得到正确的结果. 总体上看,从图形处理流水线的源头开始,需要准备好vertex和index,在立即模式下,index可以直接编程在命令中,通过配置寄存器告诉GPU vertex buffer的位置,在启动GPU流水线之前,还需要将vertex shader程序和pixel shader程序加载到vram 中,并通过配置寄存器告示GPU shader程序的位置,在vertex shader和p

【原创】Linux环境下的图形系统和AMD R600显卡编程(3)——AMD显卡简介

早期的显卡仅用于显示,后来显卡中加入了2D加速部件,这些部件用于做拷屏,画点,画线等操作.随着游戏.三维模拟以及科学计算可视化等需要,对3D的需求逐渐增加,早期图形绘制工作由CPU来完成,要达到真实感和实时效果,只能绘制一些简单的线框模型,上世纪80年代,斯坦福大学的Jim Clark教授率先提出用专用集成电路技术实现一个专用的3D图形处理器的设想,于1984年推出了世界上第一个通用图形工作站IRIS1400. AMD最早的显卡从R100开始,一直到R900(R600以后也使用HD xxxx作为

【原创】Linux环境下的图形系统和AMD R600显卡编程(7)——AMD显卡的软件中断

CPU上处理的中断可以分成“硬件中断”和“软件中断”两类,比如网卡产生的中断称为硬件中断,而如果是软件使用诸如"int 0x10"(X86平台上)这样的指令产生中断称为软件中断,硬件中断是异步的,其发生的时机是不可知的,但是软件中断是同步的,CPU是“确切”知道其发生的时机的. 同样的,在GPU开来,中断也可以分成“硬件中断”和“软件中断”两类,比如热插拔事件或者vblank事件都会产生“硬件中断”,这些事件在GPU看来是异步的,GPU不知道这些事情何时发生.GPU也可以使用类似CPU

【原创】Linux环境下的图形系统和AMD R600显卡编程(4)——AMD显卡显存管理机制

显卡使用的内存分为两部分,一部分是显卡自带的显存称为VRAM内存,另外一部分是系统主存称为GTT内存(graphics translation table和后面的GART含义相同,都是指显卡的页表,GTT 内存可以就理解为需要建立GPU页表的显存).在嵌入式系统或者集成显卡上,显卡通常是不自带显存的,而是完全使用系统内存.通常显卡上的显存访存速度数倍于系统内存,因而许多数据如果是放在显卡自带显存上,其速度将明显高于使用系统内存的情况(比如纹理,OpenGL中分普通纹理和常驻纹理). 某些内容是必

【原创】Linux环境下的图形系统和AMD R600显卡编程(11)——R600指令集

1 低级着色语言tgsi OpenGL程序使用GLSL语言对可编程图形处理器进行编程,GLSL语言(以下高级着色语言就是指GLSL)是语法类似C的高级语言,在GLSL规范中,GLSL语言被先翻译成教低级的类汇编语言,然后被翻译成硬件特定的指令集.OpenGL体系管理委员会于2002年6月和2002年9月分别通过了两个官方扩展:ARB_VERTEX_PROGRAM与ARB_FRAGMENT_PROGRAM来统一对低级着色语言的支持,GLSL语言被编译成针对这两个扩展的低级着色语言(因此这两个扩展可

【原创】Linux环境下的图形系统和AMD R600显卡编程(8)——AMD显卡DRM驱动初始化过程

前面几个blog对DRM驱动.显卡的显存管理机制.中断机制都进行了一些描述,现在阅读AMD drm驱动的初始化过程应该会轻松许多. 下面是一AMD的开发人员编写的文章(先暂时放在这里,后续有时间再添加自己的看法). Understanding GPUs from the ground up I get asked a lot about learning how to program GPUs.  Bringing up evergreen kms support seems like a go