2012-04-26 36 views
5

Tôi đang viết một trình đổ bóng phân đoạn cho WebGL (GLSL ES 1.0) bằng phiên bản mới nhất của Chrome (và Firefox) và tôi đã viết một thuật toán lặp lại. Vì vậy, trước hết, tôi phát hiện ra một cách khó khăn rằng chiều dài của vòng lặp là khá hạn chế (doc nói nó phải được đoán tại thời gian biên dịch, có nghĩa là nó phải là một hằng số hoặc rất gần).Ngăn vòng lặp trong trình đổ mảnh phân đoạn

Ngoài ra, tôi phải viết một (for, vì nó là duy nhất mà phải được triển khai theo vòng lặp tiêu chuẩn) có khả năng dài nhưng phá vỡ hầu như mọi lúc trước khi kết thúc.

Bây giờ, tôi đã nhận thấy rằng nếu tôi đặt số tối đa cao hơn thì việc biên dịch và liên kết của trình đổ bóng sẽ mất nhiều thời gian hơn. Vì vậy, trừ khi tôi là sai, trình biên dịch hiện lặp đi lặp lại.

Tôi không chắc chắn liệu có thể làm được gì không, nhưng tôi đã thử một vài thứ và trình biên dịch có vẻ như cũng có chức năng nội tuyến, ngay cả khi được gọi trong vòng lặp.

Tôi không cảm thấy bình thường khi một người đổ bóng mất một phút để biên dịch chỉ khoảng một trăm lần lặp của một vòng lặp. Hay tôi đang làm điều sai trái? Có phải hàng trăm lần lặp trong một trình đổ bóng phân mảnh quá nhiều đối với một GPU? Bởi vì nó có vẻ chạy tốt sau khi nó đã được biên dịch.

+0

WebGL thường chỉ đưa trình đổ bóng cho trình biên dịch trong thư viện OpenGL của bạn, vì vậy nó sẽ làm gì và mất bao lâu tùy thuộc vào thẻ video và trình điều khiển của bạn ... –

Trả lời

4

Đây là một trong những thực tế không may của GLSL. Nó sẽ là tuyệt vời nếu chúng ta có thể làm một biên dịch offline và gửi bytecode, hoặc nếu chúng ta có khả năng xác định cờ tại thời gian biên dịch hay như vậy, nhưng đó không phải là cách spec hoạt động. Bạn hoàn toàn ở lòng thương xót của nhà sản xuất lái xe. Nếu NVIDIA/ATI nghĩ rằng việc bỏ vòng lặp là tốt cho bạn, vòng lặp của bạn sẽ bị hủy bỏ.

Tôi đặt câu hỏi về việc bạn đang làm gì đòi hỏi phải lặp quá nhiều. Shaders không thực sự là nơi thích hợp để thực hiện các phép tính vòng lặp hoặc phân nhánh siêu phức tạp. Bạn chắc chắn sẽ có một hit hiệu suất cho nó. Nếu bạn không lo lắng về hiệu suất thời gian thực, thì có lẽ một hit biên dịch lớn khi bắt đầu chương trình của bạn không quá tệ. Nếu bạn lo ngại về tốc độ hiển thị của ứng dụng thì có thể bạn cần phải đánh giá lại độ phức tạp của trình đổ bóng.

2

Bạn đề cập đến trình đổ bóng mất hơn một phút để biên dịch vòng lặp tối đa chỉ khoảng 100 lần lặp lại và điều này khiến tôi nghĩ rằng sự cố của bạn có thể liên quan đến ANGLE. ANGLE là một phần mềm được nhúng trong các trình duyệt có khả năng WebGL trên hệ điều hành Windows, có trình đổ bóng GLSL của bạn và dịch nó khi chạy vào trình đổ bóng Direct3D HLSL. Suy nghĩ là hầu hết các máy Windows đều có trình điều khiển Direct3D mới hơn so với các trình điều khiển OpenGL của họ, vì vậy hành vi mặc định là chuyển đổi mọi thứ thành D3D. Theo kinh nghiệm của tôi, điều này có thể chậm, đặc biệt là với các vòng lặp dài như bạn mô tả, mặc dù nó cần thiết cho nhiều người dùng Windows, đặc biệt là những người dùng đồ họa dựa trên Intel.

Nếu bạn đang chạy Windows và có trình điều khiển OpenGL chất lượng tốt, chẳng hạn như trình điều khiển mới hợp lý từ nVidia hoặc AMD, bạn có thể thử tắt ANGLE để xem có khắc phục được sự cố không. Trên Google Chrome, điều này được thực hiện bằng cách chỉnh sửa biểu tượng Chrome của bạn để thêm --use-gl=desktop làm thông số dòng lệnh (trong trường 'mục tiêu' của biểu tượng) và khởi động lại trình duyệt. Đối với Firefox, bạn có thể truy cập about:config và nhập webgl vào hộp tìm kiếm và tìm kiếm webgl.prefer-native-gl và đặt thành đúng.

Hãy thử lại trình đổ bóng của bạn với ANGLE bị vô hiệu hóa và thời gian biên dịch có thể được cải thiện. Xin lưu ý đây chỉ là vấn đề với Windows, vì vậy việc chỉnh sửa các cài đặt này trên các nền tảng khác không có hiệu lực, nhưng tôi tin rằng tất cả các nền tảng khác đều sử dụng trực tiếp OpenGL gốc.

0

Đáng buồn là AMD có thể không hỗ trợ điều này, nhưng tôi nghĩ rằng NVidia có một chỉ thị không có chỉ số pragma. Đối với những người đang gặp vấn đề ngược lại, bạn sẽ gọi nó là "#pragma optionNV (bỏ đăng ký tất cả)" trong GLSL, nhưng tôi nghĩ rằng những điều sau đây sẽ ngăn không cho đăng ký. Tôi báo giá DenisR's 2008 post on the NVidia forums:

Theo mặc định, trình biên dịch sẽ hủy vòng lặp nhỏ với số lượng chuyến đi đã biết. Tuy nhiên, chỉ thị #pragma unroll có thể được sử dụng để kiểm soát việc hủy bỏ bất kỳ vòng lặp đã cho nào. Nó phải được đặt ngay trước vòng lặp và chỉ áp dụng cho vòng lặp đó. Nó được tùy ý theo sau bởi một số xác định bao nhiêu lần vòng lặp phải được unrolled.

Ví dụ, trong mẫu mã này:

vòng lặp sẽ được trải ra 5 lần. Nó là lập trình để đảm bảo rằng unrolling sẽ không ảnh hưởng đến tính chính xác của chương trình (mà nó có thể, trong ví dụ trên, nếu n nhỏ hơn 5).

#pragma unroll 1 

sẽ ngăn trình biên dịch thoát khỏi vòng lặp.

Nếu không có số nào được chỉ định sau #pragma unroll, vòng lặp sẽ được hủy hoàn toàn nếu số chuyến đi của nó là không đổi, nếu không thì số này không bị hủy.

Vì vậy, tôi sẽ tưởng tượng rằng

#pragma optionNV (unroll 1) 

có thể làm việc trong GLSL (và WebGL?). (Ví dụ: StackOverflow question selective-nvidia-pragma-optionnvunroll-all có vẻ ngụ ý điều này có thể hoạt động trong GLSL, ít nhất là trong một số nền tảng.)

Có vẻ như trong những năm gần đây, AMD có thể hỗ trợ một pragma chưa đăng ký (có thể không có trong GLSL), nhưng tôi không quen thuộc và chưa thử: unroll loops in an AMD OpenCL kernel

(Nếu sử dụng GLSL qua WebGL trong Chrome/Firefox hoặc thậm chí các trường hợp khác, hãy nhớ rằng biên dịch GLSL có thể được chuyển qua ANGLE, có thể hiển thị một chương trình phụ trợ HLSL trên Windows, có thể, tôi hiểu rất ít về điều này và không muốn truyền bá thông tin, vì vậy chắc chắn không trích dẫn điều đó, tôi chỉ cảm thấy cần chia sẻ thông tin nào tôi đã thu thập được về vấn đề này xa và sẽ sẵn sàng chỉnh sửa câu trả lời (hoặc mọi người nên cảm thấy tự do để chỉnh sửa câu trả lời này) khi có thêm thông tin được xác nhận.)

Các vấn đề liên quan