Làm thế nào để các nhà phát triển công cụ đồ họa gỡ lỗi mã đồ họa 3D của họ?


7

Tôi hiện đang cố gắng tạo một công cụ trò chơi nghiệp dư và tôi thường gặp phải các lỗi rất cơ bản (ví dụ: tôi thay đổi mã phân cấp nút và đột nhiên không có gì được hiển thị). Một số phương pháp tôi sẽ sử dụng bao gồm để theo dõi các lỗi này bao gồm:

  • Sử dụng trình gỡ lỗi IDE của tôi và rất nhiều printfcuộc gọi để xem xét những gì trong bộ nhớ.

  • Thực hiện nhiều thử nghiệm với các thông số khác nhau, đặt máy ảnh ở các vị trí khác nhau, để có cảm giác tốt hơn về những gì mã đang làm.

  • Chỉ cần vũ phu theo cách của tôi bằng cách đọc lại từng dòng mã cho đến khi tôi tìm thấy một dòng mã sai.

Những phương pháp này có vẻ chậm chạp và không hiệu quả đối với tôi. Vấn đề là, kết xuất 3D đó bao gồm rất nhiều thao tác không trực quan mà không có nhiều thứ để hình dung ngoại trừ "sản phẩm" cuối cùng; Khi tôi gặp phải một lỗi (đặc biệt là các loại lỗi "không hiển thị"), tôi thường cảm thấy như đang dò dẫm một cách mù quáng.


Vì thế.

Giả sử bạn là nhà phát triển làm việc trên Unity, Godot hoặc một số công cụ 3D khác và bạn chỉ cần thay đổi một số bước trong đường truyền kết xuất của mình và bây giờ, vì bất kỳ lý do gì, trình kết xuất khung dây hiển thị kết quả không liên tục khi kích hoạt thực thể được kích hoạt. Các "dây" đang lan tỏa khắp màn hình thay vì đại diện cho các cạnh của hình tam giác của thực thể được bó.

Làm thế nào để bạn theo dõi và sửa lỗi đó? Bạn có một quy trình làm việc cụ thể? Bạn có sử dụng một số loại công cụ phân tích GPU? Hay bạn chỉ loay hoay một cách mù quáng?

Nói cách khác, những phương pháp, công cụ và thực tiễn tốt nhất nào mà các nhà phát triển động cơ (không phải người dùng động cơ) có thể sử dụng để phân tích dữ liệu và hành vi của mã đồ họa 3D của họ (không chỉ hiệu suất của nó) để giải quyết các lỗi và lỗi một cách hiệu quả?


Có các trình gỡ lỗi đặc biệt cho đồ họa như Nvidia Nsight hoặc thậm chí là một trong các studio trực quan có nhiều tính năng. Hầu hết đều có khả năng chụp ảnh màn hình, chọn pixel và xem lịch sử chi tiết về cách nó đến đó.
Andrew Wilson

Câu trả lời:


5

Tôi đang lập trình chủ yếu trong OpenGL. Trong trường hợp này, điều đầu tiên tôi làm là thiết lập tiện ích mở rộng KHR_debug . Nó cung cấp một cách để đăng ký các tin nhắn được tạo bởi trình điều khiển GL - từ lỗi đến cảnh báo đến thông tin chi tiết về những gì trình điều khiển đang làm. Đặc biệt các trình điều khiển Linux nguồn mở (Mesa) tạo ra rất nhiều thông báo hữu ích.

Khi nói đến các công cụ, lựa chọn đầu tiên của tôi thường là ApiTrace. Nó cho phép bạn ghi lại dấu vết của tất cả các lệnh gọi API kết xuất, sau đó phát lại và kiểm tra trạng thái tại bất kỳ thời điểm nào (điều này bao gồm nội dung của bộ đệm, kết xuất mục tiêu, v.v.). Nó cũng cho phép bạn chia sẻ dấu vết với người khác, điều này rất hữu ích khi làm việc trong nhóm. Sau đó, có các công cụ khác như RenderDoc, Trình gỡ lỗi đồ họa NVIDIA Tegra, trình gỡ lỗi đồ họa của Xcode và một số công cụ khác. Dù bạn chọn, nó sẽ cải thiện công việc của bạn rất nhiều.

Một điều nữa là thử nghiệm. Một điều là xây dựng một bộ sưu tập các cảnh đơn giản làm nổi bật tính năng duy nhất của động cơ (chẳng hạn như cài đặt vật liệu khác nhau, kỹ thuật hoạt hình khác nhau, v.v.). Khi một lỗi được đưa vào codebase, điều này giúp gỡ lỗi nó (vì bạn có thể đơn giản để phân tích các trường hợp kiểm tra có sẵn) và xác minh rằng một bản sửa lỗi không vô tình phá vỡ thứ gì khác. Tôi đoán đó là điều khá phổ biến để làm; Các nhà phát triển Unity3D làm điều đó, ví dụ.

Bạn có thể mở rộng điều này và tự động hóa nó bằng cách tạo khai thác thử nghiệm, sẽ xây dựng và chạy tất cả các thử nghiệm một cách thường xuyên và xác minh rằng không có hồi quy nào xảy ra. Nếu bạn có nhiều kịch bản thử nghiệm, điều này có thể khả thi, mặc dù rõ ràng cần phải đầu tư thêm vào cơ sở hạ tầng.

Sau đó, có nhiều bài kiểm tra đơn vị "tiêu chuẩn" hơn. Một lĩnh vực tôi đã áp dụng chúng là hệ thống vật liệu dựa trên nút, có thể nhắm mục tiêu các kỹ thuật kết xuất khác nhau (chuyển tiếp, hoãn lại, bất cứ điều gì) và API. Tôi đã tiếp cận nó bằng cách viết các bài kiểm tra đơn vị tạo mã shader từ vật liệu và các cài đặt khác, biên dịch nó và đưa ra một lệnh gọi đơn giản với các đầu vào đã cho (đầu vào pixel shader). Các đầu ra được ghi vào một mục tiêu kết xuất và được tìm nạp để so sánh với các giá trị dự kiến. IMHO đây là một điều tốt đẹp để làm khi bạn có hệ thống vật liệu phức tạp, đặc biệt. với việc tạo mã shader.

Cuối cùng, các cách tiếp cận "truyền thống" hơn có thể được áp dụng cho các khu vực có thể tách rời khỏi kết xuất. Những thứ như cấu trúc dữ liệu không gian, tải tài sản và tương tự có thể được kiểm tra đơn vị / tích hợp, như áp dụng trong trường hợp cụ thể.

Chỉnh sửa: Đây là một bài đăng từ nhà phát triển Unity3D mô tả cách họ kiểm tra mã đồ họa.


Re: thử nghiệm cảnh, tôi hiện đang sử dụng các cảnh mẫu glTF để kiểm tra động cơ của mình; Tôi có thể xây dựng những cảnh phức tạp hơn vào một lúc nào đó để kiểm tra xem cái gì sẽ sai nhiều hơn.
Narrateur du hỗn loạn

Tôi đã quên về một liên kết tôi muốn đưa vào, về cách tiếp cận của Unity3D - Tôi đã chỉnh sửa câu trả lời của mình để đưa nó vào.
joe_chip

4

Tôi thường thích RenderDoc để gỡ lỗi một khung. Cung cấp cho bạn đủ thông tin về khung cụ thể được hiển thị ngay từ Vertex đến Pixel. Có những công cụ hữu ích không kém khác có sẵn như Nvidia Nsight

Cuối cùng, luôn có mã màu có thể hữu ích khi gỡ lỗi các shader một cách trực quan. Phân tách đầu ra shader thành các màu riêng biệt cũng có thể giúp đỡ. Không chắc chắn nếu trường hợp của bạn yêu cầu này.

Hi vọng điêu nay co ich.


Tôi sẽ xem xét RenderDoc. Re: shader, có công cụ nào có thể cung cấp cho bạn gỡ lỗi mạnh hơn không (ví dụ: các giá trị của các biến trung gian), hoặc là gỡ lỗi dựa trên màu?
Narrateur du hỗn loạn

2
Tôi mới dành 1h cho RenderDoc và tôi đã có thể xác nhận tính hữu dụng của nó. Nó làm cho những gì là một hỗn hợp của những con bọ bí ẩn khó hiểu trở nên dễ hiểu một cách nực cười. Cảm ơn rất nhiều!
Narrateur du hỗn loạn

3

Tôi làm việc chủ yếu trên macOS nơi các công cụ OpenGL gần như không tồn tại. (Tôi bắt đầu tham gia vào Metal nơi các công cụ tốt hơn.) Vì vậy, tôi cảm thấy nỗi đau của bạn.

Điều đầu tiên tôi làm là thực hiện thường xuyên, các cam kết nhỏ về mã của tôi để kiểm soát nguồn. Điều này không phải lúc nào cũng có thể, nhưng thường thì nó là như vậy. Nếu điều đó có thể phá vỡ những người khác, làm việc trên một chi nhánh. Theo cách đó, nếu có lỗi xảy ra khủng khiếp, tôi có thể thực hiện một cách khác biệt nhanh chóng của mã hiện tại so với CHÍNH hoặc thân cây và tách vấn đề thành chỉ mã trong các khác biệt.

Điều tiếp theo tôi làm là cố gắng phân tích vấn đề là gì. Trong ví dụ của bạn, nơi hình học đang hoạt động trước đây đột nhiên vẽ sai hình dạng, tôi nghĩ về các tình huống có thể gây ra điều đó:

  1. Gửi một con trỏ không có thật đến glBufferData()
  2. Bắt đầu sai byte của bộ đệm của tôi bằng cách đặt con trỏ thuộc tính / offset không chính xác

Có rất nhiều nguyên nhân gây ra các triệu chứng chung như màn hình đen đáng sợ. Có một số kỹ thuật tương đương với đồ họaprintf(). Tôi bắt đầu phá vỡ những gì làm việc và những gì không. Tôi bắt đầu với những nét thực sự rộng. Là bản vẽ của tôi sẽ đến đúng FBO? Đặt màu rõ ràng của FBO thành một thứ gì đó sặc sỡ như RGB = (1, 0,5, 0) hoặc (0, 1, 1) và xem màn hình chuyển sang màu cam hoặc đỏ tươi. Bạn có thể chọn một màu gỡ lỗi khác nhau cho mỗi FBO bạn thường sử dụng để bạn có thể biết trong nháy mắt sẽ hiển thị trên một kết xuất cụ thể. Nếu nó hoạt động, tôi kiểm tra những thứ như cắt các mặt phẳng - tôi đã cắt tất cả các hình học ra chưa? Kiểm tra ánh sáng - tôi có bật đèn không? Tôi có đang gửi thông tin ánh sáng chính xác cho các shader không? Kết cấu có đúng không? Nó có thể giúp có một số kết cấu thử nghiệm với những thứ như lưới trên chúng hoặc nếu bạn đang xử lý các bản đồ khối, kết cấu có tên khuôn mặt trên chúng. Nếu bạn có vấn đề về shader, bạn có thể làm những việc như chỉ đơn giản là xuất tọa độ kết cấu thành màu đỏ và màu xanh lá cây (và màu xanh nếu đó là kết cấu 3D) tại mỗi điểm để đảm bảo chúng hợp lệ. Tương tự với quy tắc - chuẩn hóa chúng và xuất rax, yztrong r, gbcác kênh truyền hình.

Khi bạn làm nhiều hơn thế, bạn sẽ học được những thủ thuật như thế này để hiển thị dữ liệu và xác minh các giả định của bạn. Có thể quay trở lại nhanh chóng và dễ dàng là rất hữu ích. Và tất nhiên, đừng quên điều đó glGetError(). Một số lượng nhỏ lỗi mà nó trả về gây khó chịu, nhưng nó thường có thể chỉ cho bạn biết hướng của một vấn đề.

Nếu bạn có thể nhận được một công cụ cho bạn thấy những gì khác với trạng thái OpenGL mặc định, thì nó cũng có thể chỉ dẫn nơi dành nỗ lực của bạn. Trên macOS có OpenGL Profiler. Bạn có thể đặt điểm dừng trên bất kỳ chức năng OpenGL nào và kiểm tra toàn bộ máy trạng thái. Nó sẽ làm nổi bật sự khác biệt từ mặc định hoặc khác biệt so với lần cuối cùng dừng lại hoặc cả hai.

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.