Làm cách nào để tải tài nguyên đồ họa không đồng bộ?


9

Chúng ta hãy nghĩ về nền tảng bất khả tri: Tôi muốn tải một số tài nguyên đồ họa trong khi phần còn lại của trò chơi đang chạy.

Về nguyên tắc, tôi có thể tải các tệp thực tế trên một luồng riêng biệt hoặc sử dụng I / O không đồng bộ. Nhưng với các đối tượng đồ họa, tôi sẽ phải tải chúng lên GPU và điều đó chỉ có thể được thực hiện trên luồng chính.

Tôi có thể thay đổi vòng lặp trò chơi của mình để trông giống như thế này:

while true do
    update()
    for each pending resource do
        load resource to gpu
    end
    draw()
end

trong khi có một luồng tài nguyên tải riêng biệt từ đĩa vào RAM.

Tuy nhiên, nếu có nhiều tài nguyên lớn để tải, điều này có thể khiến tôi bỏ lỡ thời hạn khung và cuối cùng bị rơi khung. Vì vậy, tôi có thể thay đổi vòng lặp này:

while true do
    update()
    if there are pending resources then
        load one resource to gpu
        remove that resource from the pending list
    end
    draw()
end

Hiệu quả chỉ tải một tài nguyên trên mỗi khung. Tuy nhiên, nếu có nhiều tài nguyên nhỏ để tải, tải tất cả chúng sẽ mất nhiều khung hình, và sẽ có rất nhiều thời gian lãng phí.

Tối ưu, tôi muốn tính thời gian tải theo cách sau:

while true do
    time_start = get_time()
    update()
    while there are pending resources then
        current_time = get_time()
        if (current_time - time_start) + time_to_load(resource) >= 1/60 then
            break
        load one resource to gpu
        remove that resource from the pending list
    end
    draw()
end

Bằng cách này, tôi sẽ chỉ tải một tài nguyên nếu tôi có thể làm điều đó trong thời gian tôi có cho khung đó. Thật không may, điều này đòi hỏi một cách để ước tính lượng thời gian cần thiết để tải một tài nguyên nhất định và theo như tôi biết, thường không có cách nào để làm điều này.

Tôi đang thiếu gì ở đây? Làm thế nào để nhiều trò chơi có thể tải tất cả nội dung của chúng hoàn toàn không đồng bộ và không bị rớt khung hình hoặc thời gian tải cực kỳ dài?

Câu trả lời:


7

Hãy bắt đầu bằng cách giả định một thế giới hoàn hảo. Có hai bước để tải tài nguyên: đầu tiên bạn lấy nó ra khỏi phương tiện lưu trữ và vào bộ nhớ ở định dạng chính xác và thứ hai bạn chuyển nó qua bus bộ nhớ sang bộ nhớ video. Cả hai bước này thực sự không cần phải sử dụng thời gian trên luồng chính của bạn. Nó chỉ cần tham gia để đưa ra lệnh I / O. Cả CPU và GPU của bạn có thể tiếp tục làm những việc khác trong khi tài nguyên đang được sao chép. Tài nguyên thực sự duy nhất đang được tiêu thụ là băng thông bộ nhớ.

Nếu bạn đang sử dụng một nền tảng không có nhiều lớp trừu tượng giữa bạn và phần cứng, API có thể phơi bày trực tiếp các khái niệm này. Nhưng nếu bạn đang ở trên PC, có lẽ có một trình điều khiển ngồi giữa bạn và GPU và nó muốn thực hiện mọi thứ theo cách của nó. Tùy thuộc vào API, bạn thể tạo kết cấu được hỗ trợ bởi bộ nhớ mà bạn sở hữu, nhưng nhiều khả năng gọi API "tạo kết cấu" sẽ sao chép kết cấu vào một số bộ nhớ mà trình điều khiển sở hữu. Trong trường hợp đó, việc tạo ra một kết cấu sẽ có một số chi phí cố định và một số thời gian tỷ lệ thuận với kích thước của kết cấu. Sau đó, trình điều khiển có thể làm bất cứ điều gì, nó có thể chủ động chuyển kết cấu sang VRAM hoặc không cần tải lên kết cấu cho đến khi bạn cố gắng kết xuất lần đầu tiên.

Bạn có thể hoặc không thể làm gì đó về điều đó, nhưng bạn có thể dự đoán về thời gian cần thiết để thực hiện cuộc gọi "tạo kết cấu". Tất nhiên, tất cả các con số sẽ thay đổi tùy thuộc vào phần cứng và phần mềm, vì vậy có lẽ không đáng để dành nhiều thời gian để thiết kế lại chúng. Vì vậy, hãy thử nó và xem! Chọn một số liệu: "số lượng kết cấu trên mỗi khung" hoặc "tổng kích thước của họa tiết trên mỗi khung", chọn một hạn ngạch (giả sử, 4 kết cấu trên mỗi khung) và bắt đầu kiểm tra căng thẳng.

Trong các trường hợp bệnh lý, bạn thậm chí có thể cần theo dõi cả hai hạn ngạch cùng một lúc (ví dụ: giới hạn ở 4 kết cấu trên mỗi khung hoặc 2 MB kết cấu trên mỗi khung, tùy theo mức nào thấp hơn). Nhưng lừa thực với hầu hết các kết cấu trực tuyến là tìm hiểu textures bạn muốn để phù hợp với bộ nhớ hạn chế của bạn, không có bao nhiêu thời gian để sao chép chúng xung quanh.

Ngoài ra, các trường hợp bệnh lý cho việc tạo kết cấu, giống như rất nhiều kết cấu nhỏ cần thiết cùng một lúc có xu hướng là trường hợp bệnh lý cho các khu vực khác. Thật đáng để có được một triển khai làm việc đơn giản trước khi lo lắng về việc chính xác cần bao nhiêu micrô giây để sao chép. (Ngoài ra, cú đánh hiệu năng thực sự có thể không phát sinh do thời gian CPU trong cuộc gọi "tạo kết cấu", mà thay vào đó là thời gian GPU trên khung hình đầu tiên bạn sử dụng kết cấu.)


Đó là một lời giải thích khá tốt. Nhiều thứ tôi không biết nhưng rất có ý nghĩa. Thay vì kiểm tra căng thẳng, tôi sẽ đo chi phí tạo kết cấu trong thời gian chạy, bắt đầu nhẹ nhàng và tăng tốc để nói, 80% thời gian thực hiện có sẵn để dành chỗ cho các ngoại lệ.
Panda Pyjama

@PandaPajama Tôi hơi nghi ngờ về điều đó. Tôi hy vọng trạng thái ổn định là "không có kết cấu được sao chép" và một lượng lớn phương sai. Và như tôi đã nói, tôi nghi ngờ rằng một phần của hit là khung kết xuất đầu tiên sử dụng kết cấu, khó hơn nhiều để đo động mà không ảnh hưởng đến hiệu suất.
John Calsbeek

Ngoài ra, đây là một bản trình bày NVIDIA về chuyển giao kết cấu không đồng bộ. Điều quan trọng mà nó đang lái xe về nhà, theo như tôi đang đọc, là việc sử dụng một kết cấu quá sớm sau khi bạn tải lên, nó sẽ bị đình trệ. developer.doad.nvidia.com/GTC/PDF/GTC2012/PftimeationPDF/
dọa

Tôi không phải là người lái xe dev, nhưng điều đó có phổ biến không? Điều đó không có ý nghĩa quá nhiều khi thực hiện các trình điều khiển theo cách đó, bởi vì các ứng dụng đầu tiên về kết cấu rất có thể xuất hiện đột biến (như ở đầu mỗi cấp độ) thay vì cách nhau theo dòng thời gian.
Panda Pyjama

@PandaPajama Nó cũng phổ biến cho các ứng dụng để tạo ra nhiều kết cấu hơn VRAM có sẵn, và để tạo kết cấu và sau đó không bao giờ sử dụng chúng. Một trường hợp phổ biến là "tạo ra một loạt các kết cấu và sau đó ngay lập tức vẽ một khung cảnh mà sử dụng chúng," trong trường hợp lười biếng giúp người lái xe, vì nó có thể tìm ra kết cấu đang thực sự được sử dụng, và rằng frame đầu tiên sẽ quá giang mà nào . Nhưng tôi cũng không phải là tài xế dev, hãy mang nó bằng một hạt muối (và kiểm tra nó!).
John Calsbeek
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.