跨越opengl和d3d的鴻溝(三) 交集?並集?

2021-07-23 00:01:40 字數 3646 閱讀 5980

d3d9的功能早已被opengl 2.0所覆蓋,網上可以找到很多資料,這裡就不提了。本文注重的是新的gpu特性。下表列出了d3d10+的新功能,以及實現該功能所需要的opengl擴充套件或核心。

d3d 10的功能

opengl所對應的

geomrtry shader

gl_arb_geometry_shader4或opengl 3

stream output

gl_ext_transform_feedback或opengl 3

state物件

無,需要在上層封裝gl_ext_direct_state_access

constant buffer

gl_arb_uniform_buffer_object或opengl 3

texture array和新的資源格式

gl_ext_texture_array

+gl_arb_texture_compression_rgtc

+gl_arb_texture_rg

+gl_arb_texture_rgb10_a2ui

+gl_ext_texture_integer或opengl 3

texture和sampler解偶

gl_arb_sampler_objects或opengl 3

在shader裡進行整數和位操作

gl_arb_shader_bit_encoding或opengl 3

multisampled alpha-to-coverage

gl_nv_multisample_coverage或opengl 3

d3d 10.1的功能

opengl所對應的

讀取multisample depth/stencil紋理

gl_arb_texture_multisample或opengl 3

cubemap array

gl_arb_texture_cube_map_array或opengl 4

gather4

gl_arb_texture_gather或opengl 4

d3d 11的功能

opengl所對應的

compute shader

gl_arb_cl_event + opencl

dynamic shader linkage

gl_arb_gpu_shader5或opengl 4

multithreading

無tessellation

gl_arb_tessellation_shader或opengl 4

這些都是dx sdk文件裡提到的功能,其他一些比較小的功能,也可以很容易找到opengl的對應。從上表可以看出,幾乎所有d3d的功能都可以直接用相應的opengl功能代替,同時沒有效能損失。需要重點討論的是一些例外:

d3d 10新增了state物件,可以極大地減少由於改變渲染狀態所需的系統呼叫次數。opengl中目前還沒有state物件,所以只能在上層自行封裝。雖然有些 效能損失,但介面可以和d3d統一起來。arb針對opengl的state物件進行過曠日持久的討論,還最終各大廠商沒有達成一致。不過這是個趨勢,相信不久的將來就會出個相關的擴充套件。到時候這個區別就能被完美地填平。

d3d 11引入了compute shader,在d3d中直接提供了gpgpu的能力。opengl沒有因此增加一種shader,而是增強和同門師弟opencl的互操作能力。 opengl和opencl能直接共享texture和buffer等,起到了和compute shader等價的功能。與glsl和hlsl的關係一樣,這裡存在著shader語言不同的問題,而且沒有cg可以作為橋梁,目前只能寫兩份**。

d3d 11的multithreading能力允許多個context都呼叫d3d11 api,每個context儲存下來的api呼叫流可以在主context執行依次執行。opengl目前也沒有引入該機制,需要在上層自行實現。話說回來了,目前的所有顯示卡 驅動都沒有實現multithreading,所以所有多context都是由d3d runtime軟體實現的,沒有達到應有的提速效果。自己實現乙個command list也能達到那樣的效能。仍然希望某一天multithreading能成為opengl的功能 之一,簡化上層的工作。

所以說,opengl和d3d功能的交集幾乎就是它們的並集,並不會因為需要相容兩者而失去很多功能。從功能上說,opengl和d3d之間的分歧甚至小於opengl和opengl es。破解了第一篇說的流言4。

神奇擴充套件wgl_nv_dx_interop的出現,使得opengl可以正式與d3d進行互操作。(嚴格來說,互操作能力源自它的前身wgl_nvx_dx_interop,但鑑於他是個nvx實驗性質的擴充套件,最好小心點用。)該擴充套件的目的是,在d3d中建立資源,而在 opengl中訪問它。目前可以支援的是d3d9的紋理、render target和vb的讀寫。d3d10+的支援將在未來加入。兩個api之間所需的同步也是自動完成的。

使用wgl_nv_dx_interop進行相互渲染的範例如下:

// 跟平常一樣建立d3d裝置和資源

d3d->createdevice(..., &d3ddevice);

d3ddevice->createrendertarget(width, height, d3dfmt_a8r8g8b8,

d3dmultisample_4_samples, 0,

false, &dxcolorbuffer, null);

d3ddevice->createdepthstencilsu***ce(width, height, d3dfmt_d24s8,

d3dmultisample_4_samples, 0,

false, &dxdepthbuffer, null);

// 把d3d裝置註冊給opengl

handle gl_handled3d = wgldxopendevicenv(d3ddevice);

// 把d3drender target註冊成opengl紋理物件

gluint names[2];

handle handles[2];

handles[0] = wgldxregisterobjectnv(gl_handled3d, dxcolorbuffer,

names[0], gl_texture_2d_multisample, wgl_access_read_write_nv);

handles[1] = wgldxregisterobjectnv(gl_handled3d, dxdepthbuffer,

names[0], gl_texture_2d_multisample, wgl_access_read_write_nv);

// 現在紋理就可以當成普通的opengl紋理來用了

// d3d和opengl渲到同乙個render target

direct3d_render_pass(); // 和平常一樣進行d3d渲染

// 鎖定render target,交給opengl

wgldxlockobjectsnv(handled3d, 2, handles);

opengl_render_pass(); // 和平常一樣進行opengl渲染

wgldxunlockobjectsnv(handled3d, 2, handles);

direct3d_swap_buffers(); // d3d present

這樣兩個api可以和諧共處了,但這個擴充套件目前僅限於nv的卡。

跨越OpenGL和D3D的鴻溝(一) 開篇

有人說,opengl直接調到驅動,效能高於d3d。有人說,shader都得寫兩套,很麻煩。有人說,opengl和d3d在底層有很多區別,而且不可設定。有人說,圖形引擎如果要相容兩者,就只能取其功能的交集,最後還不如任何一種api。真的麼?下面先從幾個比較基本的方面來 如何跨越兩個api的鴻溝。ope...

跨越opengl和d3d的鴻溝(一) 開篇

多年來,在論壇和各個 上不斷能看到拿opengl和d3d進行比較的帖子和文章。他們經常製造很多謎思,使得初學者和一些從業人員對opengl和d3d產生了各種各樣的流言。有人說,opengl直接調到驅動,效能高於d3d。有人說,shader都得寫兩套,很麻煩。有人說,opengl和d3d在底層有很多區...

OpenGL和D3D的區別

1 世界座標系 opengl為右手座標系d3d為左手座標系 2 裁剪空間 opengl中z的範圍 1.0,1.0 d3d為 0.0,1.0 3 shader shader開始是以彙編的形式出現,在推出一段時間後,就出現如下幾種類c的高階語言 注 這些高階語言會被編譯成顯示卡識別的彙編 opengl的...