Overview(#158)

复杂的OpenGL应用和对高分辨率的追求使纹理的大小巨增,但是可供一个GPU使用的物理内存是有限的,一旦内存使用殆尽,内存换页就可能发生,性能严重下降,或者更糟,应用直接挂了。但另一方面GPU可访问的地址空间目前已经可以达到GB,甚至TB.

Read more »

smart pointer是C11引入的,被包含在C标准库中。smart pointer是为了管理对象的所属(object ownership)而设计的,smart pointer对象负责自动地销毁所关联对象。常见的smart pointer有:

Read more »

Overview(#117)

ARB_texture_storage的主要目的是简化纹理一致性(consistency)和完整性(completeness)检查,以减小实现的开销。

Read more »

概述(#84)

传统的OpenGL纹理格式(texture format)的纹理数据存储和解释是统一的,纹理就是被解释成颜色。而在现代OpenGL应用中,大多数纹理并不是代表颜色,而是代表像shadow maps, normal maps, page tables, occlusion data等等这样的数据。对于后者,我们将纹理数据称作"RGBA",只是对数据在现有模型上的一种方便的映射,但并不是数据实际上的准确解释。

Read more »

概述(#183)

ARB_shader_ballot给一组线程(a group of invocations)提供某些形式的线程间(cross-invocation)通信的能力。它要么是通过广播某个线程作用域里的值,要么是通过一个位数组(bitarray)表示一组线程中每个线程作用域里的可能的值。

Read more »

概述(#124)

ARB_texture_view的主要目的是通过创建已有纹理对象的视图(view), 来产生新的纹理对象,以达到共享同一纹理存储(data store)的目的。它可以从以下3个方面创建纹理视图:

Read more »

概述(#14)

ARB_point_parameters允许用户设置点的扩展几何特征。这些点的几何特征主要用来渲染粒子或微小光源,通常被称为光点(Light Points).

Read more »

Visual Block Selection

  • 选择 {}(curly braces) 之间的行(包括 {})

    • v%
  • 选择 {}(curly braces) 之间的行(不包括 {})

    • vi{

注意:光标必须放在 { 或者 }

Copy & Paste

Copy to clipboard

  • Normal 模式
    • "+y

Paste from clipboard

X11 window system 有 3 个 selections:

  • PRIMARY 表示当前的可见 selection
  • SECONDARY
  • CLIPBOARD 通常所说的剪贴板,用来完成剪贴,复制和粘贴操作

Vim 有两个专门的寄存器分别与 PRIMARY selection 和 CLIPBOARD selection 对应

  • "* (quotestar) PRIMARY
  • "+ (quoteplus) CLIPBOARD

如果要在 Vim 内部剪贴,复制/粘贴就使用 quotestar, 如果要将内容剪贴,复制/粘贴到系统剪贴板,就使用 quoteplus

举个例子,在 WSL Ubuntu 里如果想粘贴 Windows 剪贴板里的内容到 vim (最好是 neovim, 因为 vim 可能未使能 clipboard)

1
echo "Hello, world!" | clip.exe
  • Normal 模式
    • "+p

如果想粘贴 Ubuntu 剪贴板里的内容

1
echo "Hello, world!" | xclip
  • Normal 模式
    • "*p

Copy from above or below

在 Insert 模式下

  • <ctrl-y> copies the character from the line above
  • <ctrl-e> copies the character from the line below (本行就是这样输入的)

Search & Replace

删除多行 C-style 注释

  • s;/\*\_.\{-}\*/;;

    • ; 因为要匹配 /, 为了省去转义 / 的麻烦,将 search 命令的分隔符由 / 改为 ;

    • /\* 匹配开始的 /*

    • \_. 匹配任意字符,包括 \n, 所以常用在多行匹配

    • \{-} 指非贪婪 (non-greedy) 匹配,即匹配最短的字串,默认是贪婪匹配,匹配最长的字串

    • \*/ 匹配结尾的 */

    • ;; 指使用空替换匹配结果,即删除

    • 以下是 vim 中在单行中使用的通配符 (wildcard), 这些通配符一般不能匹配换行 \n

      • . 匹配除了 \n 的任意字符
      • ^ 行首,即锚点 (anchor)
      • $ 行尾,即锚点
      • \s 匹配 space, tab, 但不匹配 \n
    • 以上通配符加上 \_ 后可以在多行匹配中使用,即也可以匹配 \n

      • \_. 匹配任意字符,包括 \n
      • \_^ 多行中第一行行首
      • \_$ 多行中最后一行行尾
      • \_s 匹配 space, tab 和 \n

删除空白行

  • g/^\s*$/d

    • g 指所有行搜索,而不是默认的光标所在行
    • ^\s*$ 匹配行首到行尾之间任意个空白字符,即空白行
    • d 删除命令 (delete)

搜索不匹配某模式的行,即反向搜索

  • /^\(\(^# .*$\)\@!.\)*$

    • / 查找命令 (search) 的提示符
    • ^\(\(The_Regex\)\@!.\)*$ 反向查找的命令固定模式,本例中 The_Regex^# .*$ 即以 # 开头的行,所以整个表达式匹配的就是不以 # 开头的所有行
  • :v/^# .*$/p

    • 与上面的反向查找命令功能相同, 但会将匹配结果显示在 Visual 模式下

大小写转换

  • s/\(^# .*$\)/\L\1/

    • \(The_Regex\) 为了向前索引,即后面 \1 所指的部分,本例中 The_Regex^# .*$, 意思同上
    • \L\1 \LLowercase, 即将 \1 匹配的结果中的所有字母都换成小写
  • s/\(^# .*$\)/\U\1/

    • 与上面的表达式功能相反,即将 \1 匹配的结果中的所有字母都换成大写 (Uppercase)

expression register

假如你在 markdown 文件里编辑一个 Table, table 的第1列是 find 的输出:一个很长的文件列表,且文件名长短不一(假如最长的文件名是 100 个字符),你如何在 100 列插入 vertical bar (|)?

  • N,Ms/.*/\=printf('%-101s|', submatch(0))/

    • N,M 指定替换的范围
    • \= 表示使用 expression register, 这里相当于把 printf() 函数的输出导入到这里

TOhtml

vim 有一个内置的扩展 TOhtml, 可以将 vim 的 buffer 自动转成 html 文件,这个功能对于 vimdiff 时尤其有用。

  1. :[range]TOhtml range 没有时默认是整个 buffer (vimdiff 时包括左右两个 window 哦)
  2. :wqa 生成的 html 默认保存为 Diff.html
  3. 可以将生成的 html 内容直接粘贴到 jsbin.com, 然后就可以分享给他人

X11 is designed as client-server mode. The communication between the X client and server complies with TCP protocol. Recently I have a Windows X server VcXsrv installed on my Windows 10 and I debug an OpenGL demo glxgears on the WSL2 with tcpdump.

Environment

WSL2 is equipped with its own networking interface like a virtual machine.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.28.233.193 netmask 255.255.240.0 broadcast 172.28.239.255
inet6 fe80::215:5dff:fe27:9562 prefixlen 64 scopeid 0x20<link>
ether 00:15:5d:27:95:62 txqueuelen 1000 (Ethernet)
RX packets 221579 bytes 15160108 (15.1 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 306691 bytes 15714800233 (15.7 GB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 392 bytes 43340 (43.3 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 392 bytes 43340 (43.3 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ /mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -C "ipconfig"

Windows IP Configuration


Ethernet adapter vEthernet (WSL):

Connection-specific DNS Suffix . :
Link-local IPv6 Address . . . . . : fe80::412b:ad3:5548:67ba%38
IPv4 Address. . . . . . . . . . . : 172.28.224.1
Subnet Mask . . . . . . . . . . . : 255.255.240.0
Default Gateway . . . . . . . . . :

Wireless LAN adapter ±¾µØÁ¬½Ó* 1:

Media State . . . . . . . . . . . : Media disconnected
Connection-specific DNS Suffix . :

Wireless LAN adapter ±¾µØÁ¬½Ó* 10:

Media State . . . . . . . . . . . : Media disconnected
Connection-specific DNS Suffix . :

Wireless LAN adapter WLAN:

Connection-specific DNS Suffix . : DHCP HOST
Link-local IPv6 Address . . . . . : fe80::954b:e66f:4065:20af%20
IPv4 Address. . . . . . . . . . . : 192.168.2.100
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . : 192.168.2.1

After starting up the X server VcXsrv, you need to export the environmnet variable DISPLAY on the WSL. In case of the vEthernet configuration changed after rebooting you’d better do it like this:

1
export DISPLAY=$(grep 'nameserver' /etc/resolv.conf | awk '{print $2}'):0

NOTE: The Firewall between the host and WSL2 must be disabled or your X client can not connect VcXsrv.

Debugging

I trace the demo glxgears using gdb and tcpdump at the same time.

  • gdb
1
gdb -q -tui glxgears
  • tcpdump
1
sudo tcpdump -vvX not icmp and not arp and not udp and portrange 37900-37999 -w x110224.pcap
  • vv: verboser than -v
  • X: show the packet’s content
  • not icmp: filter out icmp packets
  • not arp: filter out arp packets
  • not udp: filter out udp packets
  • portrange 37900-37999: listening on the ports from 37900 to 37999
  • w x110224.pcap: save the packet captures into the file
1
tcpdump -X -r x110224.pcap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
reading from file /home/luc/github/x110224.pcap, link-type EN10MB (Ethernet)
09:11:56.659816 IP 172.28.233.193.37950 > 172.28.224.1.x11: Flags [P.], seq 2796598646:2796598658, ack 1053772981, win 259, length 12
0x0000: 4500 0034 1d84 4000 4006 fb43 ac1c e9c1 E..4..@.@..C....
0x0010: ac1c e001 943e 1770 a6b0 b576 3ecf 4cb5 .....>.p...v>.L.
0x0020: 5018 0103 2223 0000 6200 0300 0400 0000 P..."#..b.......
0x0030: 4452 4932 DRI2
09:11:56.660218 IP 172.28.224.1.x11 > 172.28.233.193.37950: Flags [P.], seq 1:33, ack 12, win 8211, length 32
0x0000: 4500 0048 d9d7 4000 8006 fedb ac1c e001 E..H..@.........
0x0010: ac1c e9c1 1770 943e 3ecf 4cb5 a6b0 b582 .....p.>>.L.....
0x0020: 5018 2013 cf36 0000 0100 0a00 0000 0000 P....6..........
0x0030: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0x0040: 0000 0000 0000 0000 ........
09:11:56.660232 IP 172.28.233.193.37950 > 172.28.224.1.x11: Flags [.], ack 33, win 259, length 0
0x0000: 4500 0028 1d85 4000 4006 fb4e ac1c e9c1 E..(..@.@..N....
0x0010: ac1c e001 943e 1770 a6b0 b582 3ecf 4cd5 .....>.p....>.L.
0x0020: 5010 0103 2217 0000 P..."...

what codes sends and receives these packets? The first two twenty-byted segments are IP header (20 bytes without option) and TCP header (20 bytes without option) separately in these packets.

The source code snippet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Bool
XQueryExtension(
register Display *dpy,
_Xconst char *name,
int *major_opcode, /* RETURN */
int *first_event, /* RETURN */
int *first_error) /* RETURN */
{
xQueryExtensionReply rep;
register xQueryExtensionReq *req;

LockDisplay(dpy);
GetReq(QueryExtension, req);
req->nbytes = name ? strlen(name) : 0;
req->length += (req->nbytes+(unsigned)3)>>2;
_XSend(dpy, name, (long)req->nbytes);
(void) _XReply (dpy, (xReply *)&rep, 0, xTrue);
*major_opcode = rep.major_opcode;
*first_event = rep.first_event;
*first_error = rep.first_error;
UnlockDisplay(dpy);
SyncHandle();
return (rep.present);
}

The gdb log:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Starting program: /mnt/c/Users/lulu/Documents/github/demos/src/xdemos/glxgears 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, XextAddDisplay (extinfo=0x7ffff7e77380 <_dri2Info_data>, dpy=0x55555555d2a0,
ext_name=0x7ffff7e76780 <dri2ExtensionName> "DRI2", hooks=0x7ffff7e767a0 <dri2ExtensionHooks>, nevents=0, data=0x0)
at extutil.c:103
XInitExtension (dpy=dpy@entry=0x55555555d2a0, name=name@entry=0x7ffff7e76780 <dri2ExtensionName> "DRI2")
at InitExt.c:44
XQueryExtension (dpy=dpy@entry=0x55555555d2a0, name=name@entry=0x7ffff7e76780 <dri2ExtensionName> "DRI2",
major_opcode=major_opcode@entry=0x7fffffffd984, first_event=first_event@entry=0x7fffffffd988,
first_error=first_error@entry=0x7fffffffd98c) at QuExt.c:39
$2 = {
reqType = 0x62,
pad = 0x0,
length = 0x3,
nbytes = 0x4,
pad1 = 0x0,
pad2 = 0x0
}
$3 = {
type = 0x1,
pad1 = 0x0,
sequenceNumber = 0xa,
length = 0x0,
present = 0x0,
major_opcode = 0x0,
first_event = 0x0,
first_error = 0x0,
pad3 = 0x0,
pad4 = 0x0,
pad5 = 0x0,
pad6 = 0x0,
pad7 = 0x0
}

$2 is Request packet content to VcXsrv, $3 is Reply packet content from VcXsrv. Even that we can notice the three-way handshake of TCP from the zero-lengthed packet in x110224.pcap.

0%