Sử dụng bộ sưu tập để sắp xếp ngăn nắp các trang
Lưu và phân loại nội dung dựa trên lựa chọn ưu tiên của bạn.
AGI Frame Profiler cho phép bạn kiểm tra các chương trình đổ bóng bằng cách chọn một lệnh gọi vẽ từ một trong các lượt kết xuất của chúng tôi và chuyển qua phần Vertex Shader (Chương trình đổ bóng đỉnh) hoặc phần Fragment Shader (Chương trình đổ bóng mảnh) của ngăn Pipeline (Quy trình).
Tại đây, bạn sẽ thấy các số liệu thống kê hữu ích từ quá trình phân tích tĩnh mã chương trình đổ bóng, cũng như hợp ngữ Đại diện trung gian di động tiêu chuẩn (SPIR-V) mà GLSL của chúng tôi đã được biên dịch. Ngoài ra, còn có một thẻ để xem bản trình bày của GLSL gốc (với tên do trình biên dịch tạo cho các biến, hàm và nhiều thành phần khác) đã được dịch ngược bằng SPIR-V Cross, nhằm cung cấp thêm bối cảnh cho SPIR-V.
Phân tích tĩnh
Hình 1. Caption??
Sử dụng các bộ đếm phân tích tĩnh để xem các thao tác cấp thấp trong chương trình đổ bóng.
Hướng dẫn ALU: Số liệu này cho biết số lượng hoạt động ALU (cộng, nhân, chia, v.v.) đang được thực thi trong chương trình đổ bóng và là một chỉ số đại diện tốt cho mức độ phức tạp của chương trình đổ bóng. Hãy cố gắng giảm thiểu giá trị này.
Tái cấu trúc các phép tính thông thường hoặc đơn giản hoá các phép tính được thực hiện trong chương trình đổ bóng có thể giúp giảm số lượng chỉ dẫn cần thiết.
Hướng dẫn về hoạ tiết: Số liệu này cho biết số lần lấy mẫu hoạ tiết xảy ra trong chương trình đổ bóng.
Việc lấy mẫu hoạ tiết có thể tốn kém tuỳ thuộc vào loại hoạ tiết được lấy mẫu, vì vậy, việc tham chiếu chéo mã chương trình đổ bóng với các hoạ tiết được liên kết có trong phần Descriptor Sets (Tập hợp mô tả) có thể cung cấp thêm thông tin về các loại hoạ tiết đang được sử dụng.
Tránh truy cập ngẫu nhiên khi lấy mẫu hoạ tiết, vì hành vi này không phù hợp với việc lưu vào bộ nhớ đệm hoạ tiết.
Hướng dẫn về nhánh: Số liệu này cho biết số lượng thao tác nhánh trong chương trình đổ bóng. Giảm thiểu việc phân nhánh là lựa chọn lý tưởng trên các bộ xử lý song song như GPU, và thậm chí có thể giúp trình biên dịch tìm thấy các hoạt động tối ưu hoá bổ sung:
Sử dụng các hàm như min, max và clamp để tránh phải phân nhánh trên các giá trị số.
Kiểm thử chi phí tính toán trên các nhánh. Vì cả hai đường dẫn của một nhánh đều được thực thi trong nhiều cấu trúc, nên có nhiều trường hợp mà việc luôn thực hiện tính toán sẽ nhanh hơn so với việc bỏ qua tính toán bằng một nhánh.
Các thanh ghi tạm thời: Đây là các thanh ghi nhanh, trên lõi được dùng để lưu giữ kết quả của các hoạt động trung gian mà các phép tính trên GPU yêu cầu. Có một giới hạn về số lượng thanh ghi có sẵn cho các phép tính trước khi GPU phải tràn vào việc sử dụng bộ nhớ ngoài lõi khác để lưu trữ các giá trị trung gian, làm giảm hiệu suất tổng thể. (Giới hạn này thay đổi tuỳ thuộc vào kiểu GPU.)
Số lượng thanh ghi tạm thời được sử dụng có thể cao hơn dự kiến nếu trình biên dịch chương trình đổ bóng thực hiện các thao tác như mở vòng lặp, vì vậy, bạn nên tham chiếu chéo giá trị này với SPIR-V hoặc GLSL đã biên dịch ngược để xem mã đang làm gì.
Phân tích mã chương trình đổ bóng
Khám phá chính mã đổ bóng đã dịch ngược để xác định xem có thể cải thiện gì hay không.
Hình 2. Caption??
Độ chính xác: Độ chính xác của các biến chương trình đổ bóng có thể ảnh hưởng đến hiệu suất GPU của ứng dụng.
Hãy thử sử dụng bộ sửa đổi độ chính xác mediump trên các biến bất cứ khi nào có thể, vì các biến 16 bit có độ chính xác trung bình (mediump) thường nhanh hơn và tiết kiệm điện hơn so với các biến 32 bit có độ chính xác đầy đủ (highp).
Nếu bạn không thấy bất kỳ bộ đủ điều kiện độ chính xác nào trong chương trình đổ bóng trên các khai báo biến hoặc ở đầu chương trình đổ bóng có precision precision-qualifier type, thì chương trình sẽ mặc định là độ chính xác đầy đủ (highp). Hãy nhớ xem cả các khai báo biến.
Bạn cũng nên dùng mediump cho đầu ra của chương trình đổ bóng đỉnh vì những lý do tương tự như mô tả ở trên, đồng thời có lợi ích là giảm băng thông bộ nhớ và có thể giảm mức sử dụng thanh ghi tạm thời cần thiết để thực hiện nội suy.
Vùng đệm đồng nhất: Cố gắng giữ kích thước của Vùng đệm đồng nhất nhỏ nhất có thể (trong khi vẫn duy trì các quy tắc căn chỉnh). Điều này giúp các phép tính tương thích hơn với việc lưu vào bộ nhớ đệm và có thể cho phép dữ liệu đồng nhất được chuyển đến các thanh ghi trên lõi nhanh hơn.
Xoá các đầu ra Vertex Shader không dùng đến: Nếu bạn thấy các đầu ra vertex shader không được dùng trong fragment shader, hãy xoá chúng khỏi shader để giải phóng băng thông bộ nhớ và các thanh ghi tạm thời.
Di chuyển phép tính từ Trình đổ bóng phân mảnh sang Trình đổ bóng đỉnh: Nếu mã trình đổ bóng phân mảnh thực hiện các phép tính độc lập với trạng thái dành riêng cho phân mảnh đang được đổ bóng (hoặc có thể được nội suy đúng cách), thì việc di chuyển mã đó sang trình đổ bóng đỉnh là lựa chọn lý tưởng. Lý do là trong hầu hết các ứng dụng, chương trình đổ bóng đỉnh chạy ít thường xuyên hơn nhiều so với chương trình đổ bóng phân mảnh.
Nội dung và mã mẫu trên trang này phải tuân thủ các giấy phép như mô tả trong phần Giấy phép nội dung. Java và OpenJDK là nhãn hiệu hoặc nhãn hiệu đã đăng ký của Oracle và/hoặc đơn vị liên kết của Oracle.
Cập nhật lần gần đây nhất: 2025-07-27 UTC.
[[["Dễ hiểu","easyToUnderstand","thumb-up"],["Giúp tôi giải quyết được vấn đề","solvedMyProblem","thumb-up"],["Khác","otherUp","thumb-up"]],[["Thiếu thông tin tôi cần","missingTheInformationINeed","thumb-down"],["Quá phức tạp/quá nhiều bước","tooComplicatedTooManySteps","thumb-down"],["Đã lỗi thời","outOfDate","thumb-down"],["Vấn đề về bản dịch","translationIssue","thumb-down"],["Vấn đề về mẫu/mã","samplesCodeIssue","thumb-down"],["Khác","otherDown","thumb-down"]],["Cập nhật lần gần đây nhất: 2025-07-27 UTC."],[],[],null,["# Analyze shader performance\n\nAGI Frame Profiler allows you to investigate your shaders by\nselecting a draw call from one of our render passes, and going through either\nthe **Vertex Shader** section or **Fragment Shader** section of the **Pipeline**\npane.\n\nHere you'll find useful statistics coming from static analysis of the shader\ncode, as well as the [Standard Portable Intermediate Representation](https://en.wikipedia.org/wiki/Standard_Portable_Intermediate_Representation)\n(SPIR-V) assembly that our GLSL has been compiled down to. There's also a tab\nfor viewing a representation of the original GLSL (with compiler generated names for variables, functions, and more) that was decompiled with SPIR-V Cross, to provide additional context for the SPIR-V.\n\nStatic analysis\n---------------\n\n**Figure 1.**Caption??\n\nUse static analysis counters to view low-level operations in the shader.\n\n- **ALU Instructions**: This count shows the number of ALU operations\n (adds, multiplies, divisions, and more) are being executed within the\n shader, and is a good proxy for how complex the shader is. Try to minimize\n this value.\n\n Refactoring common computations or simplify computations done in the\n shader can help reduce the number of instructions needed.\n- **Texture Instructions**: This count shows the number of times texture\n sampling occurs in the shader.\n\n - Texture sampling can be expensive depending on the type of textures being sampled from, so cross-referencing the shader code with the bound textures found in the **Descriptor Sets** section can provide more information on the types of textures being used.\n - Avoid random access when sampling textures, because this behavior is not ideal for texture-caching.\n- **Branch Instructions**: This count shows the number of branch operations\n in the shader. Minimizing branching is ideal on parallelized processors such\n as the GPU, and can even help the compiler find additional optimizations:\n\n - Use functions such as `min`, `max`, and `clamp` to avoid needing to branch on numeric values.\n - Test the cost of computation over branching. Because both paths of a branch are executed in many architectures, there are many scenarios where always doing the computation is faster than skipping over the computation with a branch.\n- **Temporary Registers**: These are fast, on-core registers that are used to\n hold the results of intermediate operations required by computations on the\n GPU. There is a limit to the number of registers available for computations\n before the GPU has to spill over into using other off-core memory to store\n intermediate values, reducing overall performance. (This limit varies\n depending on the GPU model.)\n\n The number of temporary registers used may be higher than expected if the\n shader compiler performs operations such as unrolling loops, so it's good\n to cross-reference this value with the SPIR-V or decompiled GLSL to see what\n the code is doing.\n\n### Shader code analysis\n\nInvestigate the decompiled shader code itself to determine if there any\npotential improvements are possible.\n**Figure 2.**Caption??\n\n- **Precision** : The precision of shader variables can impact the GPU performance of your application.\n - Try using the `mediump` precision modifier on variables wherever possible, since medium precision (`mediump`) 16-bit variables are usually faster and more power efficient than full precision (`highp`) 32-bit variables.\n - If you don't see any precision qualifiers in the shader on variable declarations, or at the top of the shader with a `precision precision-qualifier type`, it defaults to full precision (`highp`). Make sure to look at variable declarations as well.\n - Using `mediump` for vertex shader output is also preferred for the same reasons described above, and also has the benefit of reducing memory bandwidth and potentially temporary register usage needed to do interpolation.\n- **Uniform Buffers** : Try to keep the size of **Uniform Buffers** as small as possible (while maintaining alignment rules). This helps make computations more compatible with caching and potentially allow for uniform data to be promoted to faster on-core registers.\n- **Remove unused Vertex Shader Outputs**: If you find vertex shader outputs\n being unused in the fragment shader, remove them from the shader to free up\n memory bandwidth and temporary registers.\n\n- **Move computation from Fragment Shader to Vertex Shader**: If the fragment\n shader code performs computations that are independent of state specific to\n the fragment being shaded (or can be interpolated properly), moving it to\n the vertex shader is ideal. The reason for this is that in most apps, the\n vertex shader is run much less frequently compared to the fragment shader."]]