2013-03-17 15 views
7

Ví dụ, nếu tôi sử dụng vertex như sau:GLSL có thực sự thực hiện các phép tính không cần thiết với các giá trị thống nhất (không phải trên mỗi đỉnh) không?

#version 400 core 

uniform mat4 projM; 
uniform mat4 viewM; 
uniform mat4 modelM; 

in vec4 in_Position; 

out vec4 pass_position_model; 

void main(void) { 
    gl_Position = projM * viewM * modelM * in_Position; 
    pass_position_model = modelM * in_Position; 
} 

Nó sẽ làm projM * viewM * modelM nhân ma trận cho mỗi đỉnh, hoặc nó nó đủ thông minh để tính toán, nếu một lần và không tính toán lại cho đến khi biến đồng đều được thay đổi? Nếu nó không phải là "đủ thông minh", thì có cách nào để tối ưu hóa nó ngoài việc tính toán tất cả các giá trị phụ thuộc vào thống nhất trên CPU và gửi chúng dưới dạng biến thống nhất cho GPU không?
Ngoài ra tôi quan tâm đến các giải pháp có thể được chuyển sang OpenGL ES 2.0 sau mà không gặp sự cố.

Trả lời

10

Vì vậy, không có câu trả lời chung, như tôi hiểu. Tôi đã làm một số xét nghiệm trên phần cứng của tôi, mặc dù. Tôi có 2 GPU trong khoảng không quảng cáo của mình, Intel HD Graphics 3000NVidia GeForce GT 555M. Tôi đã thử nghiệm chương trình của mình (chương trình được viết bằng java/scala) với phép nhân ma trận trong vertex shader, và sau đó di chuyển phép nhân sang chương trình CPU và được kiểm tra lại.

(sphereN - đó là một quả cầu xoay liên tục với 2 * N^2 quads, được vẽ bằng glDrawElements (GL_QUADS, ...) Với 1 kết cấu và không có bất kỳ ánh sáng/hiệu ứng khác)

nhân ma trận trong vertex:

intel: 
    sphere400: 57.17552887364208 fps 
    sphere40: 128.1394156842645 fps 
nvidia: 
    sphere400: 134.9527665317139 fps 
    sphere40: 242.0135527589545 fps 

nhân ma trận trên cpu:

intel: 
    sphere400: 57.37234652897303 fps 
    sphere40: 128.2051282051282 fps 
nvidia: 
    sphere400: 142.28799089356858 fps 
    sphere40: 247.1576866040534 fps 

xét nghiệm cho thấy rằng multiplicating (thống nhất) ma trận trong vertex shader là ý tưởng tồi, ít nhất là trên phần cứng này. Vì vậy, nói chung người ta có thể không dựa vào tối ưu hóa trình biên dịch GLSL tương ứng.

+0

Awsome. Tôi sẽ phải ghi nhớ điều đó. –

+0

+1 cho nỗ lực định hình (và sử dụng 2 card đồ họa tôi có). – GraphicsMuncher

+0

+1. Nhưng làm cách nào bạn đánh giá kết quả? Có vẻ như sự khác biệt gần như không đáng kể. Tôi đề nghị chạy cả hai mô phỏng trong 60 giây và xem xét chỉ đọc FPS tốt nhất (vì nó thể hiện hiệu năng tốt nhất mà CPU/GPU có thể làm). – Calmarius

3

Nó sẽ làm projM * viewM * mô hình nhân ma trận cho mỗi đỉnh, hoặc nó đủ thông minh để tính toán nếu một lần và không tính toán lại cho đến khi biến thống nhất được thay đổi?

Yêu cầu nhà phát triển triển khai OpenGL được đề cập. Các đặc điểm kỹ thuật OpenGL không có gì để nói về điều này, nhưng trình điều khiển và trình biên dịch GLSL nhà văn có thể đã thực hiện tối ưu hóa cho việc này.

Nếu nó không phải là "đủ thông minh", sau đó là có một cách để tối ưu hóa nó khác hơn tính toán tất cả các giá trị thống nhất phụ thuộc vào CPU và gửi chúng dưới dạng các biến thống nhất cho GPU?

Không. Bạn phải tự mình thực hiện công việc này.

+0

Nếu tôi chỉ quan tâm đến tình huống với một vài nhà cung cấp hàng đầu hiện nay, ví dụ như NVidia, AMD, PoverVR, thì câu hỏi có thể dễ dàng hơn? –

+0

@SargeBorsch: Nó không trở nên dễ dàng hơn để trả lời, bởi vì tối ưu hóa như thế này thường được giữ bí mật thương mại. Ít nhất là đối với các trình điều khiển nguồn mở của dự án Mesa bạn có thể thấy những gì họ làm. Nhưng với các trình điều khiển nguồn đóng từ NVidia, AMD và Imaginon không thể đưa ra một tuyên bố rõ ràng. – datenwolf

1

Tất cả các tối ưu hóa OpenGL và GLSL đều là nhà cung cấp cụ thể. Nó là khá khó để nói đầu ra cuối cùng từ trình biên dịch glsl là gì.

Bạn có thể xem tại đây để biết thông tin cụ thể nhà cung cấp: http://renderingpipeline.com/graphics-literature/low-level-gpu-documentation/

Đối với mã của bạn, bạn có thể luôn luôn 'gói' ma trận vào bộ đồng phục mới: matModelViewProjection, nhân nó trong ứng dụng và gửi nó vào vertex shader.

0

Điều đó phụ thuộc hoàn toàn vào trình điều khiển. OpenGL là một đặc điểm kỹ thuật, nếu bạn trả tiền cho họ để có quyền thực hiện một cuộc xâm lược, họ sẽ cung cấp cho bạn một lời giải thích mẫu để sử dụng, nhưng đó là nó.

Bên cạnh đó bạn cần xem xét các hạn chế nhân ma trận, làm projM * viewM * modelM * vertex không giống như thực hiện vertex * projM * viewM * modelM. Đó là bởi vì ma trận được nhân từ phải sang trái, và thứ tự quan trọng với điều đó. Vì vậy, trình đổ bóng không thể tính toán trước projM * viewM * modelM để chia sẻ giữa các đỉnh, bởi vì điều đó sẽ cho bạn kết quả không có thật.

+0

Bạn có chắc chắn không? 'projM * viewM * modelM * in_Position' bằng với' (projM * viewM * modelM) * in_Position' (ít nhất, nó cho các khung không thể phân biệt trong chương trình của tôi, trong đó tất cả 3 ma trận không phải là tầm thường). Nhưng ma trận thực sự được nhân lên từ phải sang trái. –

+0

Thật sao? lẻ. Để chạy thử nghiệm, sử dụng máy tính của bạn, bạn có thể tạo một chương trình đơn giản tính toán ma trận 'projM * viewM * modelM' trên CPU và ** sau đó ** chuyển nó tới trình đổ bóng. Ngoài ra, bạn sẽ có thể xem những gì nó kết thúc được với 'glGetShaderSource', để xem nếu nó làm bất cứ điều gì kỳ lạ với mã của bạn trước khi biên dịch. –

+0

Gần đây tôi đã đọc một acticle trên Internet về điều đó, nó nói rằng đó là tối ưu hóa hợp lệ để thay đổi 'M1 * M2 * v' thành' M1 * (M2 * v) ', vì vậy nó có thể được thực hiện ngược, nếu M1 * M2 là precomputed. Thật không may, tôi không thể tìm thấy liên kết đến nó: ( –