圖像生成的整個過程在 OS 內核以及顯卡內的詳細執行流程是什麼樣的?
圖像生成的整個過程在OS內核以及顯卡內的詳細執行流程,能否通俗形象的解釋?多謝!鄙人斗膽給出自己的理解,但是僅僅是猜測,總感覺不踏實,希望高手們答疑解惑,多謝!
第一步:某用戶態代碼要在屏幕上生成一個白色圓形,在屏幕正中央。其直接調用D3D庫,比如D3D庫中有某個函數:drawcircle(顏色圖.坐標)。問題1:D3D庫頂層暴露的API就是這樣的么?是不是還有畫線,畫方,梯形,同心圓等等?能否舉個D3D里某函數的實際名字和參數?
第二步:drawcircle()接收到調用之後,是不是繼續調用庫里的一些演算法函數,這些演算法函數會知道「屏幕上某某坐標像素填充成白色」這種信息,猜測其返回值是一個屏幕像素的bitmap,被置1的表示填充白色?如果是這樣的話,好像圖像的運算過程並沒有被GPU加速,而是CPU算的。那麼,畫圓這個過程,D3D庫應該生成什麼樣的信息,將什麼信息傳遞給顯卡?問題2:D3D庫底層函數輸出的是什麼樣的返回值,描述了什麼樣的信息?能否給個實例,多謝。問題3:D3D庫底層又向下調用了誰?是顯卡驅動么?第三步:D3D庫根據應用程序的畫圖需求,生成對應的描述信息(具體是什麼樣的?),然後調用顯卡驅動,將這些信息傳遞給顯卡進行渲染。問題4:顯卡驅動據說分為用戶態和內核態兩部分,用戶態驅動又分成多個層次,都有哪些層次以及各個層次具體的作用?
問題5:顯卡內部也是數千個CPU來執行指令,那麼D3D庫是不是需要把用戶的畫圖需求,編譯成供GPU里的核心執行的二進位代碼,然後通過顯卡驅動發送給顯卡?這個編譯過程,具體是誰執行的,D3D庫?還是顯卡驅動?能否具體說說?第四步:GPU接收到驅動發送的二進位代碼,那麼,GPU中數千個核心,接收到的代碼具體被載入哪個核運行?問題6:驅動發送給GPU的代碼中是不是會明確給出「該代碼載入xx號核心運行」這種信息?然後輪流發送數千個指令包給數千個核心執行。還是說,同一個任務發給GPU之後,GPU內部自行進行切分處理?問題7:關於Framebuffer這個東西,有人說其就是直接把GPU的顯存通過MMIO映射到CPU物理地址空間。是這樣的么?假設我在玩遊戲,後台突然有個進程嘗試寫了Framebuffer,在中央生成一個圓形,這個圓形會和遊戲圖像一起顯示在屏幕上么?問題8:刷新率的問題,GPU是不是以一定的頻率從顯存中將要輸出的像素讀出然後輸出到HDMI?還是說只向顯示器傳送變化的像素?問題9:假設某個遊戲畫面,處於靜止狀態,屏幕上沒有任何像素變化,那麼此時遊戲程序還會繼續向顯卡傳遞需要渲染的數據么?以上步驟,期望高手能夠幫忙修改成準確的描述,並針對性回答對應的問題,多謝!
1. 沒有,D3D並不提供畫圓,只有畫三角形這樣最基本的primitive。
2. 理想狀況下,上層應該負責把圓轉成三角形的表達,交給D3D。「底層函數輸出的是什麼樣的返回值」,這句話真看不懂。到底是輸出還是返回值。3. user mode driver和極少數kernel mode。4.Windows Display Driver Model (WDDM) Architecture (Windows Drivers)
Display miniport dirver:
A device type-specific kernel-mode driver, usually implemented as a dynamic-link library, that provides an interface between a port driver and the system"s hardware. Windows operating systems define the architecture of the following kinds of miniport drivers:
- An HBA-specific driver, linked against the system-supplied SCSI port driver, that drives one or more SCSI buses, or a mass-storage device driver that uses the NT SCSI port driver as its interface to the system.
- A video-adapter-specific driver, linked against the system-supplied video port driver, that supports a corresponding display driver.
- A network-adapter-specific driver, linked against the system-supplied NDIS library.
回答一下4,7, 8, 9問題。
問題4:顯卡驅動據說分為用戶態和內核態兩部分,用戶態驅動又分成多個層次,都有哪些層次以及各個層次具體的作用?
Q4:確實區分用戶態內核態。前面幾個回答給出了Windows下的架構。對於Linux下的,請參考我的另一個回答:計算機底層是如何訪問顯卡的? - Jet Chen 的回答問題7:關於Framebuffer這個東西,有人說其就是直接把GPU的顯存通過MMIO映射到CPU物理地址空間。是這樣的么?假設我在玩遊戲,後台突然有個進程嘗試寫了Framebuffer,在中央生成一個圓形,這個圓形會和遊戲圖像一起顯示在屏幕上么?
Q7: 首先要搞清楚MMIO映射的是寄存器,而不是內存。物理內存在地址空間的映射是BIOS配置內存控制器實現的,虛擬地址對於物理地址的映射是通過頁表映射的。內核虛擬地址到用戶進程空間的虛擬地址映射是靠mmap系統調用或者驅動提供的ioctl。如果有人寫了活動的Framebuffer,那麼肯定會顯示到屏幕上。Framebuffer可能會有很多個,一般當前只有一個的內容被輸出的屏幕上。但是不是誰都可以寫Framebuffer,就跟文件一樣,Framebuffer也需要許可權才能訪問。一般只有特殊程序才能通過驅動來修改Framebuffer的內容,比如窗口管理程序。
問題8:刷新率的問題,GPU是不是以一定的頻率從顯存中將要輸出的像素讀出然後輸出到HDMI?還是說只向顯示器傳送變化的像素?
GPU中有個部件叫做DC,Display Controller。他會以預設的頻率從Framebuffer中讀出像素去輸出。主流的DC都是讀取全部。不過你說的只讀變化的像素到時一個不錯的想法。只不過這個讀取的帶寬很大,目前不是瓶頸。也許將來4K, 8K普及了,吞吐量需求高了,真的會要做到差異更新。
問題9:假設某個遊戲畫面,處於靜止狀態,屏幕上沒有任何像素變化,那麼此時遊戲程序還會繼續向顯卡傳遞需要渲染的數據么?一般來講會的。DC一旦設置好,就會固定頻率從FrameBuffer讀取數據。不論是不是變化。其實DC也不知道Framebuffer是否有被修改過。但是在一些低功耗平台上,有些驅動程序會在已知圖像不會修改的時候,為了省電,暫時關閉DC,從而屏幕圖像靜止。但這不是主流做法。推薦閱讀:
※數字圖像處理與CG有多大聯繫?與遊戲引擎有多大聯繫?
※計算機圖形學當前熱點是什麼?
※如何理解OpenGL中著色器,渲染管線,光柵化等概念?
※什麼類型的人需要學習 OpenGL?
※想用C++實現一個軟體渲染器,類似DX和OpenGL,除了《3D遊戲編程大師技巧》,或者什麼網站推薦?