OpenGL hoạt động như thế nào ở mức thấp nhất? [đóng cửa]


84

Tôi hiểu cách viết các chương trình OpenGL / DirectX và tôi biết các phép toán và khái niệm đằng sau nó, nhưng tôi tò mò cách giao tiếp GPU-CPU hoạt động ở mức thấp.

Giả sử tôi có một chương trình OpenGL được viết bằng C hiển thị một hình tam giác và xoay máy ảnh 45 độ. Khi tôi biên dịch chương trình này, nó sẽ được chuyển thành một chuỗi các lệnh gọi ioctl và trình điều khiển gpu sau đó sẽ gửi các lệnh thích hợp đến gpu, nơi tất cả logic của việc xoay tam giác và đặt các pixel thích hợp có màu thích hợp được kết nối trong? Hay chương trình sẽ được biên dịch thành một "chương trình gpu" được tải vào gpu và tính toán vòng quay, v.v.? Hay một cái gì đó hoàn toàn khác?

Chỉnh sửa : Vài ngày sau, tôi tìm thấy loạt bài này, về cơ bản trả lời câu hỏi: http://fgiesen.wordpress.com/2011/07/01/a-trip-through-the-graphics-pipeline-2011-part- 1 /


Đặc tả OpenGL trạng thái rằng các lệnh được gửi ở chế độ máy khách / máy chủ. Thông số kỹ thuật quá rộng để xác định một công nghệ cụ thể được sử dụng bởi các triển khai OpenGL.
Luca

Câu trả lời:


86

Câu hỏi này hầu như không thể trả lời vì bản thân OpenGL chỉ là một API giao diện người dùng và miễn là việc triển khai tuân thủ đặc điểm kỹ thuật và kết quả phù hợp với điều này, nó có thể được thực hiện theo bất kỳ cách nào bạn muốn.

Câu hỏi có thể là: Trình điều khiển OpenGL hoạt động như thế nào ở mức thấp nhất. Bây giờ điều này một lần nữa là không thể trả lời nói chung, vì trình điều khiển được gắn chặt với một số phần cứng, điều này có thể một lần nữa làm những việc theo cách nhà phát triển thiết kế.

Vì vậy, câu hỏi đáng lẽ phải là: "Nhìn trung bình đằng sau hậu trường của OpenGL và hệ thống đồ họa như thế nào?". Hãy xem xét điều này từ dưới lên:

  1. Ở mức thấp nhất có một số thiết bị đồ họa. Ngày nay, đây là những GPU cung cấp một tập hợp các thanh ghi điều khiển hoạt động của chúng (chính xác là các thanh ghi này phụ thuộc vào thiết bị) có một số bộ nhớ chương trình cho trình tạo bóng, bộ nhớ lớn cho dữ liệu đầu vào (đỉnh, kết cấu, v.v.) và một kênh I / O cho phần còn lại của hệ thống mà nó nhận / gửi dữ liệu và các luồng lệnh.

  2. Trình điều khiển đồ họa theo dõi trạng thái GPU và tất cả các chương trình ứng dụng tài nguyên sử dụng GPU. Ngoài ra, nó chịu trách nhiệm chuyển đổi hoặc bất kỳ xử lý nào khác đối với dữ liệu được gửi bởi các ứng dụng (chuyển đổi kết cấu thành pixelformat được hỗ trợ bởi GPU, biên dịch shader trong mã máy của GPU). Hơn nữa, nó cung cấp một số giao diện trừu tượng, phụ thuộc vào trình điều khiển cho các chương trình ứng dụng.

  3. Sau đó, có thư viện / trình điều khiển máy khách OpenGL phụ thuộc vào trình điều khiển. Trên Windows, điều này được tải bằng proxy thông qua opengl32.dll, trên hệ thống Unix, điều này nằm ở hai nơi:

    • Mô-đun X11 GLX và trình điều khiển GLX phụ thuộc vào trình điều khiển
    • và /usr/lib/libGL.so có thể chứa một số nội dung phụ thuộc vào trình điều khiển để hiển thị trực tiếp

    Trên MacOS X, đây là "OpenGL Framework".

    Chính phần này sẽ dịch các cuộc gọi OpenGL theo cách bạn thực hiện thành các lệnh gọi tới các chức năng cụ thể của trình điều khiển trong phần của trình điều khiển được mô tả trong (2).

  4. Cuối cùng là thư viện API OpenGL thực tế, opengl32.dll trong Windows và trên Unix /usr/lib/libGL.so; điều này chủ yếu chỉ chuyển các lệnh đến việc triển khai OpenGL thích hợp.

Không thể khái quát hóa cách giao tiếp thực tế xảy ra:

Trong Unix, kết nối 3 <-> 4 có thể xảy ra qua Sockets (có, nó có thể và thực hiện qua mạng nếu bạn muốn) hoặc thông qua Shared Memory. Trong Windows, thư viện giao diện và ứng dụng khách trình điều khiển đều được tải vào không gian địa chỉ tiến trình, vì vậy không có quá nhiều giao tiếp mà chỉ là các lệnh gọi hàm đơn giản và truyền biến / con trỏ. Trong MacOS X, điều này tương tự như Windows, chỉ có điều là không có sự tách biệt giữa giao diện OpenGL và ứng dụng khách trình điều khiển (đó là lý do tại sao MacOS X rất chậm để theo kịp các phiên bản OpenGL mới, nó luôn yêu cầu nâng cấp toàn bộ hệ điều hành để mang đến cái mới khuôn khổ).

Giao tiếp betwen 3 <-> 2 có thể đi qua ioctl, đọc / ghi hoặc thông qua ánh xạ một số bộ nhớ vào không gian địa chỉ quy trình và định cấu hình MMU để kích hoạt một số mã trình điều khiển bất cứ khi nào thay đổi bộ nhớ đó được thực hiện. Điều này khá giống với bất kỳ hệ điều hành nào vì bạn luôn phải vượt qua ranh giới kernel / userland: Cuối cùng thì bạn cũng phải trải qua một số syscall.

Giao tiếp giữa hệ thống và GPU diễn ra thông qua bus periphial và các phương thức truy cập mà nó xác định, vì vậy PCI, AGP, PCI-E, v.v., hoạt động thông qua Port-I / O, Memory Mapped I / O, DMA, IRQs.


1
Mô tả này có lẽ quá thấp và chung chung với rất ít chi tiết cụ thể về OpenGL. Nó gần như áp dụng cho bất kỳ thành phần phần cứng nào có trong máy tính.
v.shashenko

1
@ v.shashenko: Tất nhiên rồi. Bất kể thành phần phần cứng nào bạn đang nói chuyện, nó tuân theo sơ đồ chung này. Nhưng OpenGL không phải là một phần mềm cụ thể, nó chỉ là một thông số kỹ thuật và bất cứ thứ gì phù hợp với đặc điểm kỹ thuật đó đều là một bản triển khai hợp lệ. Và bởi vì cuối cùng, triển khai OpenGL đang nói chuyện với GPU, nó sẽ gần như tuân theo cùng một tập lệnh mà các API đối mặt với phần cứng được triển khai. Không thể trở nên cụ thể hơn thế, bởi vì không có triển khai OpenGL " The ONE ". Và mọi cách thực hiện đều có một chút khác biệt.
datenwolf vào

1
@ v.shashenko: Nếu bạn muốn biết thêm chi tiết, thì bạn phải hỏi về một cách triển khai cụ thể. Ví dụ: X11 + GLX + DRI → Mesa / AMDGPU → Linux-KMS + DRM (Trình quản lý kết xuất trực tiếp). Và mỗi thành phần này là một con thú khá phức tạp với rất nhiều chi tiết, đến mức bạn có thể điền vào sách các chi tiết về cách hoạt động của từng thành phần. Nhưng điều đó sẽ mô tả việc triển khai Linux-AMDGPU. Nhưng Linux + NVidia là một con thú hoàn toàn khác. Và trên Windows lại khác.
datenwolf

Bạn có nhớ tôi chúng ta đã trò chuyện trong vài ngày dài trước đây, tôi chỉ muốn biết cách liên hệ với bạn trong trường hợp tôi muốn biết điều gì đó.?
Suraj Jain

Những gì bạn đã dạy ngày hôm đó, giải tỏa nhiều nghi ngờ của tôi, cũng tạo ra một số cái mới, nhưng nhìn chung, bây giờ tôi không coi việc chúng tôi vẽ các cửa sổ và biểu tượng trên màn hình là một phép thuật.
Suraj Jain

23

Khi tôi biên dịch chương trình này, nó sẽ được chuyển thành một chuỗi các lệnh gọi ioctl và trình điều khiển gpu sau đó sẽ gửi các lệnh thích hợp đến gpu, nơi tất cả logic của việc xoay hình tam giác và đặt các pixel thích hợp có màu thích hợp được kết nối trong? Hay chương trình sẽ được biên dịch thành một "chương trình gpu" được tải vào gpu và tính toán vòng quay, v.v.?

Bạn không còn xa. Chương trình của bạn gọi trình điều khiển máy khách có thể cài đặt (thực sự không phải là trình điều khiển, nó là một thư viện chia sẻ không gian người dùng). Điều đó sẽ sử dụng ioctl hoặc một cơ chế tương tự để chuyển dữ liệu đến trình điều khiển hạt nhân.

Đối với phần tiếp theo, nó phụ thuộc vào phần cứng. Các thẻ video cũ hơn có cái được gọi là "đường ống chức năng cố định". Có không gian bộ nhớ dành riêng trong thẻ video cho ma trận và phần cứng chuyên dụng để tra cứu kết cấu, kết hợp, v.v. Trình điều khiển video sẽ tải dữ liệu và cờ phù hợp cho từng đơn vị này và sau đó thiết lập DMA để truyền dữ liệu đỉnh của bạn (vị trí , màu sắc, tọa độ kết cấu, v.v.).

Phần cứng mới hơn có các lõi xử lý ("shader") bên trong card màn hình, khác với CPU của bạn ở chỗ mỗi lõi chạy chậm hơn nhiều, nhưng có nhiều lõi khác hoạt động song song. Đối với các thẻ video này, trình điều khiển chuẩn bị các chương trình nhị phân để chạy trên bộ tạo bóng GPU.


20

Chương trình của bạn không được biên dịch cho bất kỳ GPU cụ thể nào; nó chỉ được liên kết động với một thư viện sẽ triển khai OpenGL. Việc triển khai thực tế có thể liên quan đến việc gửi các lệnh OpenGL tới GPU, chạy dự phòng phần mềm, biên dịch các trình tạo bóng và gửi chúng đến GPU hoặc thậm chí sử dụng các dự phòng đổ bóng cho các lệnh OpenGL. Cảnh quan đồ họa khá phức tạp. Rất may, liên kết cách ly bạn khỏi hầu hết sự phức tạp của trình điều khiển, cho phép những người triển khai trình điều khiển tự do sử dụng bất kỳ kỹ thuật nào họ thấy phù hợp.


18

Các trình biên dịch / liên kết C / C ++ làm chính xác một điều: chúng chuyển đổi các tệp văn bản thành một loạt các mã opcode dành riêng cho máy được chạy trên CPU. OpenGL và Direct3D chỉ là các API C / C ++; chúng không thể chuyển đổi một cách kỳ diệu trình biên dịch / trình liên kết C / C ++ của bạn thành trình biên dịch / trình liên kết cho GPU.

Mọi dòng mã C / C ++ bạn viết sẽ được thực thi trên CPU. Các lệnh gọi tới OpenGL / Direct3D sẽ gọi vào các thư viện C / C ++, tĩnh hoặc động tùy từng trường hợp.

Nơi duy nhất khi "chương trình gpu" có hiệu lực là nếu mã của bạn tạo ra các trình tạo bóng. Đó là, nếu bạn thực hiện các lệnh gọi API vào OpenGL / D3D gây ra việc biên dịch và liên kết các trình tạo bóng. Để làm điều này, bạn (trong thời gian chạy, không phải thời gian biên dịch C / C ++) tạo hoặc tải các chuỗi đại diện cho trình tạo bóng bằng một số ngôn ngữ trình tạo bóng. Sau đó, bạn chuyển chúng qua trình biên dịch shader và lấy lại một đối tượng trong API đại diện cho shader đó. Sau đó, bạn áp dụng một hoặc nhiều bộ đổ bóng cho một lệnh kết xuất cụ thể. Mỗi bước trong số này diễn ra rõ ràng theo hướng mã C / C ++ của bạn, mã này như đã nêu trước đó chạy trên CPU.

Nhiều ngôn ngữ đổ bóng sử dụng cú pháp giống như C / C ++. Nhưng điều đó không làm cho chúng tương đương với C / C ++.


Tôi đã học opengl từ cuối năm nay và đã tự hỏi tại sao tôi thấy tất cả các "chương trình đổ bóng" này trong mã mà tôi nhìn thấy được viết dưới dạng chuỗi nhỏ. Giống như bạn đã nói, chúng được biên dịch tại thời điểm chạy. Tôi đã thấy một số ví dụ trong một số mã opengl es android. Sau đó, tôi thấy một số mã cho iphone quá. Rõ ràng iPhone có bốn bộ xử lý vectơ có thể thực hiện phép toán dấu phẩy động nhanh hơn nhiều so với CPU của iPhone - vì vậy bạn có thể viết ASM dưới dạng chuỗi chữ để được biên dịch tại thời điểm chạy để sử dụng các bộ xử lý đó thay vì CPU chính.
eggie 5

1
Hầu hết "đường ống chức năng cố định" hiện được thực hiện bởi một bộ chương trình đổ bóng mặc định. Bạn không cần phải yêu cầu rõ ràng một shader để có được một cái.
Ben Voigt

1
@Ben Voigt: Đúng, nhưng nếu không ai nói với bạn, bạn sẽ không thể phân biệt được.
Nicol Bolas

1
Đó có thể là một thái độ hợp lý để thực hiện, nếu câu hỏi này không phải về những chi tiết ẩn.
Ben Voigt
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.