Băng thông là gì và nó hoạt động như thế nào?


18

Các tài liệu OpenGL khẳng định fwidth đó returns the sum of the absolute value of derivatives in x and y.

Điều này có nghĩa gì trong các thuật ngữ toán học ít hơn, và có cách nào để hình dung nó?

Dựa trên sự hiểu biết của tôi về chức năng, fwidth(p)có quyền truy cập vào giá trị của pcác pixel lân cận. Làm thế nào điều này hoạt động trên GPU mà không ảnh hưởng mạnh đến hiệu suất và nó hoạt động đáng tin cậy và thống nhất trên tất cả các pixel?

Câu trả lời:


18

Pixel dẫn xuất màn hình không gian làm mạnh hiệu suất tác động, nhưng họ ảnh hưởng đến tốc cho dù bạn sử dụng chúng hay không, vì vậy từ một điểm nhất định xem họ đang miễn phí!

Mỗi GPU trong lịch sử gần đây kết hợp một phần tư bốn pixel với nhau và đặt chúng vào cùng một warp / wavefront, điều đó có nghĩa là chúng đang chạy ngay cạnh nhau trên GPU, vì vậy việc truy cập các giá trị từ chúng là rất rẻ. Vì các sợi dọc / mặt sóng được chạy theo bước khóa, các pixel khác cũng sẽ ở cùng một vị trí trong trình đổ bóng như bạn, vì vậy giá trị của pcác pixel đó sẽ chỉ nằm trong một thanh ghi chờ bạn. Ba pixel khác sẽ luôn được thực thi, ngay cả khi kết quả của chúng sẽ bị ném đi. Vì vậy, một hình tam giác bao phủ một pixel sẽ luôn che bốn pixel và loại bỏ kết quả của ba trong số chúng, để các tính năng phái sinh này hoạt động!

Đây được coi là một chi phí có thể chấp nhận (đối với phần cứng hiện tại) bởi vì nó không chỉ là các chức năng như fwidthvậy sử dụng các dẫn xuất này: mỗi mẫu kết cấu duy nhất cũng vậy, để chọn mipmap của kết cấu của bạn để đọc từ đâu. Hãy xem xét: nếu bạn ở rất gần một bề mặt, tọa độ UV bạn đang sử dụng để lấy mẫu kết cấu sẽ có đạo hàm rất nhỏ trong không gian màn hình, nghĩa là bạn cần sử dụng mipmap lớn hơn và nếu bạn ở xa hơn thì tọa độ UV sẽ có một đạo hàm lớn hơn trong không gian màn hình, có nghĩa là bạn cần sử dụng một mipmap nhỏ hơn.

Theo như những gì nó có nghĩa trong thuật ngữ ít toán học: fwidthtương đương với abs(dFdx(p)) + abs(dFdy(p)). dFdx(p)chỉ đơn giản là sự khác biệt giữa giá trị ptại pixel x + 1 và giá trị ptại pixel x, và tương tự cho dFdy(p).


Vì vậy, nếu dFdx(p) = p(x1) - p(x), sau đó x1có thể là (x+1)hoặc (x-1), tùy thuộc vào vị trí của pixel xtrong quad. Dù bằng cách nào, x1phải ở trong cùng một sợi dọc / sóng x. Tôi có đúng không?
ApoorvaJ

3
@ApoorvaJ Về cơ bản, cùng một giá trị dFdxđược tính cho mỗi 2 pixel lân cận trong lưới 2x2. Và giá trị này chỉ được tính bằng cách sử dụng sự khác biệt giữa hai giá trị lân cận, nếu đó là p(x+1)-p(x)hoặc p(x)-p(x-1)chỉ phụ thuộc vào quan niệm của bạn về những gì xchính xác ở đây. Kết quả là như nhau tuy nhiên. Vì vậy, yeah, bạn đã đúng.
Chris nói phục hồi Monica

@ChristianRau Đó là câu trả lời cho câu hỏi của tôi. Cảm ơn.
ApoorvaJ

11

Trong thuật ngữ hoàn toàn kỹ thuật, fwidth(p)được định nghĩa là

fwidth(p) := abs(dFdx(p)) + abs(dFdy(p))

dFdx(p)/ dFdy(p)là các dẫn xuất một phần của giá trị pđối với kích thước xymàn hình. Vì vậy, chúng biểu thị giá trị của phành vi khi đi một pixel sang phải ( x) hoặc một pixel lên ( y).

Bây giờ làm thế nào họ có thể được tính toán thực tế? Chà, nếu bạn biết các giá trị của các pixel lân cận p, bạn chỉ có thể tính các đạo hàm đó là các khác biệt hữu hạn trực tiếp như là một xấp xỉ cho các đạo hàm toán học thực tế của chúng (có thể không có giải pháp phân tích chính xác nào cả):

dFdx(p) := p(x+1) - p(x)

Nhưng tất nhiên bây giờ bạn có thể hỏi, làm thế nào chúng ta thậm chí biết các giá trị của p(mà sau đó có thể là bất kỳ giá trị được tính toán tùy ý nào trong chương trình đổ bóng) cho các pixel lân cận? Làm thế nào để chúng ta tính toán các giá trị đó mà không phải chịu chi phí lớn bằng cách thực hiện toàn bộ tính toán shader hai (hoặc ba) lần?

Chà, bạn biết không, những giá trị lân cận đó được tính toán bằng mọi giá, vì đối với pixel lân cận, bạn cũng chạy một shader mảnh. Vì vậy, tất cả những gì bạn cần là truy cập vào lời gọi shader mảnh vỡ lân cận này khi chạy cho pixel lân cận. Nhưng nó thậm chí còn dễ dàng hơn, bởi vì những giá trị lân cận đó cũng được tính toán cùng một lúc.

Các trình raster hiện đại gọi các shader mảnh trong các ô lớn hơn nhiều pixel lân cận. Ở mức nhỏ nhất sẽ là một lưới pixel 2x2. Và với mỗi khối pixel như vậy, shader mảnh được gọi cho từng pixel và các lệnh đó chạy theo bước khóa song song hoàn hảo để tất cả các phép tính được thực hiện theo cùng một thứ tự chính xác và cùng một lúc cho từng pixel đó trong khối (đó cũng là lý do tại sao phân nhánh trong shader mảnh, trong khi không gây chết người, nên tránh nếu có thể, vì mỗi lần gọi của một khối sẽ phải khám phá mọi nhánh được lấy bởi ít nhất một trong số các lệnh, ngay cả khi nó bị ném đi kết quả sau đó, cũng như đã nhấn mạnh trong các câu trả lời cho câu hỏi liên quan này). Vì vậy, tại bất kỳ thời điểm nào, về mặt lý thuyết, một shader mảnh vỡ có quyền truy cập vào các giá trị shader mảnh của các pixel lân cận. Và trong khi bạn không có quyền truy cập trực tiếp đến những giá trị đó, bạn có quyền truy cập vào các giá trị tính toán từ họ, như các chức năng phái sinh dFdx, dFdy, fwidth, ...

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.