Vấn đề gì làm tăng gấp đôi hoặc gấp ba bộ đệm trong các trò chơi hiện đại?


31

Tôi muốn kiểm tra xem sự hiểu biết của tôi về nguyên nhân sử dụng bộ đệm đôi (hoặc gấp ba) có đúng không:

Một màn hình với 60Hz làm mới màn hình hiển thị 60 lần mỗi giây. Nếu màn hình làm mới màn hình hiển thị, anh ta cập nhật pixel cho pixel và line cho line. Màn hình yêu cầu các giá trị màu cho các pixel từ bộ nhớ video.

Nếu tôi chạy bây giờ một trò chơi, thì trò chơi này liên tục thao túng bộ nhớ video này.

Nếu trò chơi này không sử dụng chiến lược đệm (đệm đôi, v.v.) thì vấn đề sau có thể xảy ra:

Màn hình hiện đang làm mới màn hình hiển thị của mình. Tại thời điểm này, màn hình đã làm mới nửa màn hình hiển thị đầu tiên. Đồng thời, trò chơi đã thao túng bộ nhớ video với dữ liệu mới. Bây giờ màn hình truy cập cho nửa màn hình thứ hai - hiển thị dữ liệu được thao tác mới này từ bộ nhớ video. Các vấn đề có thể bị rách hoặc nhấp nháy.

Sự hiểu biết của tôi về các trường hợp sử dụng chiến lược đệm là chính xác? Có những lý do khác?

Câu trả lời:


62

Về cơ bản, một mục tiêu cốt lõi trong kết xuất là cho mỗi khung hình được hiển thị trên màn hình để hiển thị một hình ảnh duy nhất, mạch lạc. Có một số chiến lược khác nhau, hoặc đã được sử dụng để đạt được điều này.

Sau đây, tôi đề cập đến "vsync". Vsync là thời điểm mà màn hình bắt đầu vẽ một hình ảnh màn hình mới; đó là điểm "vblank" bắt đầu trên màn hình CRT truyền thống, tại đó đường quét trong giây lát dừng vẽ và di chuyển trở lại đỉnh màn hình. Thời điểm này là rất quan trọng đối với nhiều phương pháp tiếp cận khung kết hợp.

"Xé" là những gì chúng ta gọi nó khi một màn hình hiển thị từ hai hình ảnh khác nhau, trong một khung hình duy nhất. Ví dụ, nếu tôi đã vẽ hai hình ảnh màn hình dự định hiển thị lần lượt từng cái, nhưng màn hình thay vào đó hiển thị nửa trên của khung một và nửa dưới của khung hai, đó là "xé". Điều này xảy ra do thay đổi dữ liệu mà màn hình đang đọc trong khi màn hình đang vẽ, thay vì trong vblank. (Trong các chương trình hiện đại, điều này thường xảy ra do người dùng bị vô hiệu hóa đang chờ vsync trong cài đặt trình điều khiển của họ)

Bộ đệm không

Trên phần cứng cũ nhất, thường không đủ bộ nhớ để giữ hình ảnh toàn màn hình và vì vậy thay vì vẽ hình ảnh màn hình, bạn cần chỉ định màu cho từng đường quét riêng lẻ, trong khi màn hình đang trong quá trình vẽ đường đó. Ví dụ, trên Atari 2600, bạn chỉ có 76 chu kỳ hướng dẫn máy để chỉ định màu nào đi vào từng pixel của đường quét, trước khi TV bắt đầu vẽ đường quét đó. Và sau đó bạn đã có 76 chu kỳ hướng dẫn để cung cấp nội dung cho lần quét tiếp theo , v.v.

Bộ đệm đơn

Khi vẽ trong ngữ cảnh "bộ đệm đơn", bạn đang vẽ thẳng vào VRAM đang được màn hình đọc từ đó. Trong phương pháp này, bạn "đua đường quét". Ý tưởng chung là khi đường quét bắt đầu vẽ nội dung của khung trước đó ở phía trên màn hình, bạn vẽ vào VRAM đằng sau nó. Vì vậy, trong khi đường quét đang vẽ hình ảnh màn hình cho khung cuối cùng, bạn đang vẽ khung tiếp theo phía sau đường quét.

Nói chung, bạn đang cố gắng hoàn thành việc vẽ hình ảnh khung tiếp theo trước khi đường quét "mất" bạn bằng cách quay lại lần nữa và vượt qua các pixel mà bạn đang vẽ và cũng không bao giờ vượt lên trước đường quét hoặc nếu không thì mới khung có thể vẽ vào những gì nên là khung trước đó.

Vì lý do này, kết xuất bộ đệm đơn thường hoạt động bằng cách vẽ các đường quét, từ trên xuống dưới và từ trái sang phải. Nếu bạn đã vẽ theo một số thứ tự khác, có khả năng đường quét sẽ xuất hiện trở lại và phát hiện ra các bit của hình ảnh "tiếp theo" mà bạn chưa có xung quanh để vẽ.

Lưu ý rằng trong các hệ điều hành hiện đại, bạn thường không bao giờ có cơ hội vẽ một bộ đệm, mặc dù điều này khá phổ biến cách đây ba mươi năm. (trời ạ, tôi cảm thấy già ngay bây giờ - đây là những gì tôi đã làm khi mới bắt đầu phát triển trò chơi)

Bộ đệm đôi

Điều này là rất nhiều, đơn giản hơn nhiều so với một trong những chiến lược đã đến trước đó.

Trong hệ thống đệm đôi, chúng tôi có đủ bộ nhớ để lưu trữ hai hình ảnh màn hình khác nhau và do đó chúng tôi chỉ định một trong số chúng là "bộ đệm trước" và bộ đệm còn lại là "bộ đệm phía sau". "Bộ đệm trước" là những gì hiện đang được hiển thị và "bộ đệm phía sau" là nơi chúng tôi hiện đang vẽ.

Sau khi hoàn thành việc vẽ một hình ảnh màn hình vào bộ đệm phía sau, chúng ta đợi cho đến khi vsync, và sau đó trao đổi hai bộ đệm. Bằng cách này, bộ đệm phía sau trở thành bộ đệm phía trước và ngược lại, và toàn bộ trao đổi đã xảy ra trong khi màn hình không vẽ bất cứ thứ gì.

Bộ đệm ba

Một vấn đề thường được nêu ra với các cách tiếp cận bộ đệm đôi là sau khi chúng ta vẽ xong bộ đệm phía sau, chúng ta chỉ cần ngồi chờ đợi vsync trước khi có thể trao đổi bộ đệm và tiếp tục làm việc; chúng ta có thể đã làm các phép tính trong thời gian đó! Hơn nữa, tất cả thời gian chúng tôi đang chờ để trao đổi giữa các bộ đệm, hình ảnh trong bộ đệm phía sau đó ngày càng cũ hơn, do đó làm tăng độ trễ nhận thức của người dùng.

Trong các hệ thống bộ đệm ba, chúng tôi tạo cho mình ba bộ đệm - một bộ đệm trước và hai bộ đệm phía sau. Ý tưởng là thế này:

Màn hình đang hiển thị bộ đệm phía trước và chúng tôi đang vẽ vào bộ đệm phía sau # 1. Nếu chúng ta hoàn thành vẽ vào bộ đệm phía sau số 1 trước khi màn hình hoàn thành việc vẽ bộ đệm trước, thì thay vì chờ vsync, chúng ta thay vào đó ngay lập tức bắt đầu vẽ khung tiếp theo vào bộ đệm phía sau # 2. Nếu chúng tôi kết thúc và vsync vẫn chưa đến, chúng tôi bắt đầu vẽ lại vào bộ đệm trở lại # 1, v.v. Ý tưởng là khi vsync cuối cùng xảy ra, một hoặc một trong các bộ đệm phía sau của chúng tôi sẽ hoàn tất và một cái có thể được hoán đổi cho bộ đệm phía trước.

Lợi ích của bộ đệm ba là chúng ta không mất thời gian chờ đợi vsync trong cách tiếp cận bộ đệm đôi và hình ảnh được hoán đổi trên bộ đệm trước có thể "tươi hơn" so với thời gian chờ đợi vsync 8ms. Mặt trái của bộ đệm ba là chúng ta cần thêm bộ nhớ để lưu trữ hình ảnh màn hình phụ và việc sử dụng CPU / GPU của chúng ta sẽ cao hơn (một lần nữa, vì chúng ta không chậm lại để chờ vsync).

Thông thường, các trình điều khiển hiện đại thường sẽ thực hiện bộ đệm ba trong suốt, phía sau hậu trường. Bạn viết mã của mình để thực hiện đệm đôi và trình điều khiển sẽ thực sự trả lại quyền kiểm soát cho bạn sớm và chỉ xử lý nội bộ trao đổi giữa nhiều bộ đệm trở lại mà nó muốn sử dụng mà không cần mã của bạn biết về nó.

Các nhà cung cấp GPU hiện khuyên bạn không nên tự thực hiện bộ đệm ba lần - trình điều khiển sẽ tự động làm điều đó cho bạn.


7
Đây là một câu trả lời cực kỳ chi tiết và giải thích tại sao rất nhiều thứ được thực hiện theo cách của chúng (như không gian tọa độ màn hình, v.v.). Cũng trả lời câu hỏi của tôi "tại sao không tăng gấp bốn lần bộ đệm? Quintuple?" Tôi đã không nhận ra rằng việc hoán đổi bộ đệm đã xảy ra trong nền, có nghĩa là hai bộ đệm trở lại là mức tối đa cần thiết. Nâng cao.
bữa ăn trưa317

Trên thực tế tồn tại bộ đệm quad. Đây là bộ đệm đôi cho chế độ xem lập thể. swiftless.com/tutorials/opengl/smooth_rotation.html
Narek

@Narek Không. Trích dẫn từ liên kết của bạn: "Bạn thực sự không thể kích hoạt bộ đệm thực tế trong môi trường đồ họa máy tính vì không có điểm thực". Đề xuất rằng thực hiện đệm đôi trên hai chế độ xem khác nhau đồng thời sẽ là "bộ đệm bốn" chỉ là trò chơi chữ thú vị; không phải cái gì đó thực sự
Trevor Powell

@TrevorPowell Thêm một phần mà bạn quên bao gồm: "Chà, điển hình là bộ đệm quad đề cập đến bộ đệm đôi trong môi trường lập thể. Ví dụ: Bạn có hai màn hình, thường dành cho mục đích 3D và mỗi mắt được đệm đôi." Bây giờ bối cảnh có thể rõ ràng hơn.
Narek

@TrevorPowell Quan điểm của bạn hoàn toàn rõ ràng. Không có nghĩa là có nhiều hơn 3 bộ đệm cho một bộ đệm kết xuất.
Narek
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.