Trang chủ » làm thế nào để » Làm thế nào để CPU và GPU tương tác để kết xuất đồ họa máy tính?

    Làm thế nào để CPU và GPU tương tác để kết xuất đồ họa máy tính?

    Bộ xử lý trung tâm (CPU) và Bộ xử lý đồ họa (GPU) của máy tính của bạn tương tác mỗi khi bạn sử dụng máy tính để cung cấp cho bạn giao diện trực quan sắc nét và nhạy bén. Đọc để hiểu rõ hơn về cách họ làm việc cùng nhau.

    ảnh chụp bởi sskennel.

    Phiên hỏi và trả lời hôm nay đến với chúng tôi nhờ SuperUser - một phân ngành của Stack Exchange, một nhóm các trang web hỏi đáp trong cộng đồng.

    Câu hỏi

    Độc giả của SuperUser Sathya đã đặt ra câu hỏi:

    Tại đây, bạn có thể thấy ảnh chụp màn hình của một chương trình C ++ nhỏ có tên Triangle.exe với hình tam giác xoay dựa trên API OpenGL.

    Phải thừa nhận một ví dụ rất cơ bản nhưng tôi nghĩ nó có thể áp dụng cho các hoạt động card đồ họa khác.

    Tôi chỉ tò mò và muốn biết toàn bộ quá trình từ khi nhấp đúp vào Triangle.exe trong Windows XP cho đến khi tôi có thể thấy hình tam giác xoay trên màn hình. Điều gì xảy ra, làm thế nào CPU (lần đầu tiên xử lý .exe) và GPU (cuối cùng xuất ra hình tam giác trên màn hình) tương tác?

    Tôi đoán liên quan đến việc hiển thị tam giác xoay này chủ yếu là phần cứng / phần mềm sau đây:

    Phần cứng

    • Ổ cứng
    • Bộ nhớ hệ thống (RAM)
    • CPU
    • Bộ nhớ video
    • GPU
    • Màn hình LCD

    Phần mềm

    • Hệ điều hành
    • API DirectX / OpenGL
    • Trình điều khiển Nvidia

    Bất cứ ai có thể giải thích quá trình, có thể với một số loại biểu đồ cho minh họa?

    Nó không phải là một lời giải thích phức tạp bao gồm từng bước (đoán rằng sẽ vượt ra ngoài phạm vi), nhưng một lời giải thích mà một anh chàng IT trung cấp có thể làm theo.

    Tôi khá chắc chắn rằng nhiều người thậm chí tự gọi mình là chuyên gia CNTT không thể mô tả chính xác quy trình này.

    Câu trả lời

    Mặc dù nhiều thành viên cộng đồng đã trả lời câu hỏi, Oliver Salzburg đã đi xa hơn và trả lời nó không chỉ bằng một câu trả lời chi tiết mà đồ họa đi kèm tuyệt vời.

    Hình ảnh của JasonC, có sẵn làm hình nền ở đây.

    Anh ấy viết:

    Tôi quyết định viết một chút về khía cạnh lập trình và cách các thành phần nói chuyện với nhau. Có lẽ nó sẽ làm sáng tỏ một số lĩnh vực nhất định.

    Sự trình bày

    Điều gì làm cho nó thậm chí có hình ảnh duy nhất, mà bạn đã đăng trong câu hỏi của bạn, được vẽ trên màn hình?

    Có nhiều cách để vẽ một hình tam giác trên màn hình. Để đơn giản, giả sử không có bộ đệm đỉnh được sử dụng. (Một đỉnh đệmlà một vùng bộ nhớ nơi bạn lưu trữ tọa độ.) Giả sử chương trình chỉ đơn giản là nói với đường ống xử lý đồ họa về mọi đỉnh (một đỉnh chỉ là tọa độ trong không gian) liên tiếp.

    Nhưng, trước khi chúng ta có thể vẽ bất cứ thứ gì, trước tiên chúng ta phải chạy một số giàn giáo. Chúng ta sẽ thấy tại sao một lát sau:

    // Xóa màn hình và bộ đệm sâu GlClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Đặt lại Ma trận Modelview hiện tại glMatrixMode (GL_MODELVIEW); glLoadIdentity (); // Vẽ bằng tam giác glBegin (GL_TRIANGLES); // Đỏ glColor3f (1.0f, 0.0f, 0.0f); // Đỉnh của tam giác (Mặt trước) glVertex3f (0.0f, 1.0f, 0.0f); // Màu xanh lá cây glColor3f (0.0f, 1.0f, 0.0f); // Trái của tam giác (Mặt trước) glVertex3f (-1.0f, -1.0f, 1.0f); // Màu xanh glColor3f (0.0f, 0.0f, 1.0f); // Quyền của tam giác (Mặt trước) glVertex3f (1.0f, -1.0f, 1.0f); // Xong Vẽ glEnd ();

    Vậy điều đó đã làm gì?

    Khi bạn viết chương trình muốn sử dụng card đồ họa, bạn thường sẽ chọn một số loại giao diện cho trình điều khiển. Một số giao diện nổi tiếng với trình điều khiển là:

    • OpenGL
    • Direct3D
    • CUDA

    Trong ví dụ này, chúng tôi sẽ gắn bó với OpenGL. Bây giờ, của bạn giao diện với trình điều khiển là những gì cung cấp cho bạn tất cả các công cụ bạn cần để thực hiện chương trình của bạn nói chuyện vào card đồ họa (hoặc trình điều khiển, sau đó nói chuyện vào thẻ).

    Giao diện này chắc chắn sẽ cung cấp cho bạn một số công cụ. Các công cụ này có hình dạng của API mà bạn có thể gọi từ chương trình của mình.

    API đó là những gì chúng ta thấy đang được sử dụng trong ví dụ trên. Hãy xem xét kỹ hơn.

    Giàn giáo

    Trước khi bạn thực sự có thể thực hiện bất kỳ bản vẽ thực tế nào, bạn sẽ phải thực hiện một thiết lập. Bạn phải xác định chế độ xem của mình (khu vực sẽ thực sự được hiển thị), phối cảnh của bạn ( Máy ảnh vào thế giới của bạn), bạn sẽ sử dụng loại khử răng cưa nào (để làm phẳng đường viền của hình tam giác của bạn)

    Nhưng chúng tôi sẽ không nhìn vào bất kỳ điều đó. Chúng tôi sẽ chỉ xem qua những thứ bạn sẽ phải làm mọi khung hình. Như:

    Xóa màn hình

    Các đường ống đồ họa sẽ không xóa màn hình cho bạn mọi khung hình. Bạn sẽ phải nói với nó. Tại sao? Đây là lý do tại sao:

    Nếu bạn không xóa màn hình, bạn sẽ chỉ cần vẽ qua nó mỗi khung hình. Đó là lý do tại sao chúng ta gọi glClear vớiGL_COLOR_BUFFER_BIT bộ. Một chút khác (GL_DEPTH_BUFFER_BIT) nói với OpenGL để xóa độ sâuđệm. Bộ đệm này được sử dụng để xác định các pixel ở phía trước (hoặc phía sau) các pixel khác.

    Biến đổi


    Nguồn hình ảnh

    Biến đổi là phần mà chúng ta lấy tất cả các tọa độ đầu vào (các đỉnh của tam giác) và áp dụng ma trận ModelView của chúng ta. Đây là ma trận giải thích chúng ta như thế nào mô hình (các đỉnh) được xoay, thu nhỏ và dịch (di chuyển).

    Tiếp theo, chúng tôi áp dụng ma trận Chiếu của chúng tôi. Điều này di chuyển tất cả các tọa độ để chúng đối mặt với máy ảnh của chúng tôi một cách chính xác.

    Bây giờ chúng tôi biến đổi một lần nữa, với ma trận Viewport của chúng tôi. Chúng tôi làm điều này để mở rộng quy mô của chúng tôi mô hình đến kích thước của màn hình của chúng tôi. Bây giờ chúng ta có một tập hợp các đỉnh đã sẵn sàng để được hiển thị!

    Chúng ta sẽ quay lại để biến đổi một chút sau.

    Vẽ

    Để vẽ một hình tam giác, chúng ta chỉ cần nói với OpenGL để bắt đầu một hình mới danh sách các hình tam giác bằng cách gọi glBegin với GL_TRIANGLES không thay đổi.
    Ngoài ra còn có các hình thức khác bạn có thể vẽ. Giống như một dải tam giác hoặc một quạt tam giác. Đây chủ yếu là tối ưu hóa, vì chúng yêu cầu ít giao tiếp hơn giữa CPU và GPU để vẽ cùng một số lượng tam giác.

    Sau đó, chúng tôi có thể cung cấp một danh sách gồm 3 đỉnh sẽ tạo thành mỗi tam giác. Mỗi tam giác sử dụng 3 tọa độ (như chúng ta đang ở trong không gian 3D). Ngoài ra, tôi cũng cung cấp một màu cho mỗi đỉnh, bằng cách gọiglColor3f trước gọi glVertex3f.

    Độ bóng giữa 3 đỉnh (3 góc của tam giác) được tính bằng OpenGLtự động. Nó sẽ nội suy màu trên toàn bộ mặt của đa giác.

    Sự tương tác

    Bây giờ, khi bạn nhấp vào cửa sổ. Ứng dụng chỉ phải chụp thông báo cửa sổ báo hiệu nhấp chuột. Sau đó, bạn có thể chạy bất kỳ hành động nào trong chương trình bạn muốn.

    Điều này nhận được một nhiều khó khăn hơn một khi bạn muốn bắt đầu tương tác với cảnh 3D của mình.

    Trước tiên bạn phải biết rõ pixel mà người dùng đã nhấp vào cửa sổ. Sau đó, lấy của bạn quan điểmvào tài khoản, bạn có thể tính toán hướng của tia, từ điểm chuột nhấp vào cảnh của bạn. Sau đó, bạn có thể tính toán nếu có bất kỳ đối tượng nào trong cảnh của bạn giao nhau với tia đó. Bây giờ bạn biết nếu người dùng nhấp vào một đối tượng.

    Vì vậy, làm thế nào để bạn làm cho nó xoay?

    Biến đổi

    Tôi biết hai loại biến đổi thường được áp dụng:

    • Chuyển đổi dựa trên ma trận
    • Chuyển đổi dựa trên xương

    Sự khác biệt là xương ảnh hưởng đến đơn đỉnh. Ma trận luôn ảnh hưởng đến tất cả các đỉnh được vẽ theo cùng một cách. Hãy xem một ví dụ.

    Thí dụ

    Trước đó, chúng tôi đã tải ma trận danh tính trước khi vẽ tam giác của chúng ta. Ma trận danh tính là một ma trận đơn giản cung cấp không biến đổi ở tất cả. Vì vậy, bất cứ điều gì tôi vẽ, chỉ bị ảnh hưởng bởi quan điểm của tôi. Vì vậy, tam giác sẽ không được quay.

    Nếu tôi muốn xoay nó ngay bây giờ, tôi có thể tự mình làm toán (trên CPU) và chỉ cần gọi glVertex3f vớikhác tọa độ (được quay). Hoặc tôi có thể để GPU làm tất cả công việc, bằng cách gọi glRotateftrước khi vẽ:

    // Xoay tam giác trên trục Y glRotatef (số tiền, 0,0f, 1.0f, 0.0f); 

    số tiền tất nhiên, chỉ là một giá trị cố định. Nếu bạn muốn animate, bạn sẽ phải theo dõi số tiềnvà tăng nó lên từng khung.

    Vì vậy, chờ đợi, những gì đã xảy ra với tất cả các ma trận nói chuyện trước đó?

    Trong ví dụ đơn giản này, chúng ta không cần phải quan tâm đến ma trận. Chúng tôi chỉ đơn giản gọi glRotatef và nó chăm sóc tất cả những thứ đó cho chúng tôi.

    glRotate tạo ra một vòng quay của góc độ quanh vectơ x y z. Ma trận hiện tại (seeglMatrixMode) được nhân với một ma trận xoay với sản phẩm thay thế ma trận hiện tại, vì ifglMultMatrix được gọi với ma trận sau làm đối số của nó:

    x 2 ⁡ 1 - c + cx ⁢ y ⁡ 1 - c - z ⁢ sx ⁢ z ⁡ 1 - c + y ⁢ s 0 y ⁢ x ⁡ 1 - c + z ⁢ sy 2 ⁡ 1 - c + cy ⁢ z ⁡ 1 - c - x ⁢ s 0 x ⁢ z ⁡ 1 - c - y ⁢ sy ⁢ z ⁡ 1 - c + x ⁢ sz 2 ⁡ 1 - c + c 0 0 0 0 1

    Vâng, cảm ơn vì điều đó!

    Phần kết luận

    Điều rõ ràng là, có rất nhiều chuyện đến OpenGL. Nhưng nó không nói chúng tôi bất cứ điều gì Thông tin liên lạc ở đâu?

    Điều duy nhất mà OpenGL đang nói với chúng ta trong ví dụ này là khi nào nó hoàn thành. Mỗi hoạt động sẽ mất một khoảng thời gian nhất định. Một số thao tác mất nhiều thời gian, một số khác thì cực kỳ nhanh.

    Gửi một đỉnh với GPU sẽ rất nhanh, tôi thậm chí sẽ không biết cách thể hiện nó. Gửi hàng ngàn đỉnh từ CPU đến GPU, mỗi khung hình, rất có thể, không có vấn đề gì cả.

    Xóa màn hình có thể mất một phần nghìn giây hoặc tệ hơn (lưu ý, bạn thường chỉ có khoảng 16 mili giây để vẽ mỗi khung hình), tùy thuộc vào mức độ quan sát của bạn lớn như thế nào. Để xóa nó, OpenGL phải vẽ từng pixel theo màu bạn muốn xóa, đó có thể là hàng triệu pixel.

    Ngoài ra, chúng tôi chỉ có thể hỏi OpenGL về các khả năng của bộ điều hợp đồ họa của chúng tôi (độ phân giải tối đa, khử răng cưa tối đa, độ sâu màu tối đa, Thẻ).

    Nhưng chúng ta cũng có thể điền vào một kết cấu với các pixel mà mỗi pixel có một màu cụ thể. Do đó, mỗi pixel chứa một giá trị và kết cấu là một tập tin khổng lồ, có thể chứa đầy dữ liệu. Chúng ta có thể tải nó vào card đồ họa (bằng cách tạo bộ đệm kết cấu), sau đó tải một shader, nói với shader đó sử dụng kết cấu của chúng ta làm đầu vào và chạy một số tính toán cực kỳ nặng nề trên tập tin ED của chúng ta.

    Sau đó, chúng ta có thể kết xuất lại, kết quả tính toán của chúng ta (dưới dạng màu mới) thành một kết cấu mới.

    Đó là cách bạn có thể làm cho GPU hoạt động cho bạn theo những cách khác. Tôi cho rằng CUDA thực hiện tương tự như khía cạnh đó, nhưng tôi chưa bao giờ có cơ hội làm việc với nó.

    Chúng tôi thực sự chỉ chạm nhẹ vào toàn bộ chủ đề. Lập trình đồ họa 3D là một địa ngục của một con quái vật.


    Nguồn hình ảnh


    Có một cái gì đó để thêm vào lời giải thích? Tắt âm thanh trong các ý kiến. Bạn muốn đọc thêm câu trả lời từ những người dùng Stack Exchange am hiểu công nghệ khác? Kiểm tra chủ đề thảo luận đầy đủ ở đây.