Quản lý trạng thái đồ họa và các thành phần?


11

Tôi thường có xu hướng làm tối ưu hóa sớm khi làm việc với đồ họa. Có một vài nguyên tắc tôi luôn cố gắng tuân theo:

  • Giữ số lượng thành phần D3D ở mức tối thiểu. (Kết xuất trạng thái, bộ đệm, đổ bóng, v.v.)
  • Chỉ ràng buộc các thành phần nếu thực sự cần thiết. (Chưa bị ràng buộc, v.v.)
  • Chuyên các thành phần càng nhiều càng tốt. (Chỉ đặt BindFlags cần thiết, v.v.)

Điều này dẫn tôi đến việc xây dựng các trình bao bọc rất công phu để quản lý các thành phần được tạo và trạng thái đường ống hiện tại. Điều này không chỉ tiêu tốn rất nhiều thời gian phát triển quý giá của tôi, mà còn thêm một lớp phức tạp lớn khác.

Và điều tồi tệ nhất: tôi thậm chí không biết liệu tất cả có đáng để gặp rắc rối không.

Một số cân nhắc tối ưu hóa của tôi có thể đã được triển khai ở cấp độ thấp hơn và tôi chỉ sao chép chúng, ngoài ra còn lãng phí thời gian cho CPU. Những cân nhắc khác có thể hoàn toàn không cần thiết, vì ảnh hưởng đến hiệu suất là không đáng kể.

Vì vậy, câu hỏi của tôi là:

  1. Những hướng dẫn trên là hợp lệ và tôi nên tuân theo chúng ở mức độ nào?
  2. Làm thế nào để GPU xử lý các thay đổi trạng thái?
  3. Điều gì xảy ra nếu tôi thay đổi trạng thái không bao giờ được sử dụng? (Không có cuộc gọi rút thăm nào được thực hiện trong khi nó đang hoạt động.)
  4. Các hình phạt hiệu suất thực tế để ràng buộc các thành phần khác nhau là gì?
  5. Những cân nhắc hiệu suất khác nên được thực hiện?

Xin đừng nói với tôi rằng tôi không nên quan tâm đến hiệu suất cho đến khi tôi đạt đến giới hạn thực tế. Trong khi điều đó rõ ràng là đúng theo quan điểm thực tế, tôi chủ yếu quan tâm đến lý thuyết. Bằng cách nào đó tôi cần phải chống lại sự thôi thúc xây dựng khung đồ họa tối ưu và tôi không nghĩ mình có thể làm điều đó với "bài giảng tối ưu hóa sớm" thông thường.

Quản lý linh kiện

Tôi hiện đang viết các ứng dụng DirectX 11 trong C # bằng cách sử dụng SlimDX làm trình bao bọc được quản lý. Nó là một trình bao bọc cấp độ rất thấp và sự trừu tượng hiện tại của tôi được xây dựng trên nó.

Có một số lợi thế rõ ràng khi sử dụng trừu tượng Direct3D. Thiết lập môi trường, tải shaders, thiết lập các hằng số và vẽ một lưới là đơn giản hơn nhiều và sử dụng rất nhiều mã ít hơn. Ngoài ra, vì nó quản lý việc tạo và xử lý hầu hết các thành phần, chúng có thể được tự động sử dụng lại ở mọi nơi và tôi gần như hoàn toàn tránh rò rỉ bộ nhớ.

  1. Làm thế nào để bạn thường quản lý tất cả các thành phần đồ họa và tài nguyên?
  2. Bạn có thể đề nghị bất kỳ trình bao bọc được quản lý nào làm một cái gì đó tương tự như ví dụ của tôi dưới đây không?

Dưới đây là một ví dụ về việc thực hiện hiện tại của tôi. Tôi khá hài lòng với giao diện. Nó có đủ linh hoạt cho nhu cầu của tôi và rất đơn giản để sử dụng và hiểu:

// Init D3D environment
var window = new RenderForm();
var d3d = new Direct3D(window, GraphicsSettings.Default);
var graphics = new GraphicsManager(d3d.Device);

// Load assets
var mesh = GeometryPackage.FromFile(d3d, "teapot.gp");
var texture = Texture.FromFile(d3d, "bricks.dds");

// Render states
graphics.SetViewports(new Viewport(0, 0, 800, 600);
graphics.SetRasterizer(wireFrame: false, culling: CullMode.Back);
graphics.SetDepthState(depthEnabled: true, depthWriteEnabled: true);
graphics.SetBlendState(BlendMethod.Transparency);

// Input layout
graphics.SetLayout("effect.fx", "VS", "vs_4_0",
    new InputElement("POSITION", 0, Format.R32G32B32_Float, 0),
    new InputElement("TEXCOORD", 0, Format.R32G32_Float, 0)
);

// Vertex shader
graphics.SetShader(Shader.Vertex, "effect.fx", "VS", "vs_4_0");
graphics.SetConstants(Shader.Vertex, 0, 4, stream => stream.Write(wvpMatrix));

// Pixel shader
graphics.SetShader(Shader.Pixel, "effect.fx", "PS", "ps_4_0");
graphics.SetTexture(Shader.Pixel, 0, texture);
graphics.SetSampler(Shader.Pixel, 0, Sampler.AnisotropicWrap);
graphics.SetConstants(Shader.Pixel, 0, 1, stream => stream.Write(new Color4(1, 0, 1, 0);

d3d.Run(() =>
{
    // Draw and present
    d3d.BackBuffer.Clear(new Color4(1, 0, 0.5f, 1));
    graphics.SetOutput(d3d.BackBuffer);
    graphics.Draw(mesh);
    d3d.Present();
}

8
Đối với loại câu hỏi này, tôi sẽ không cung cấp bài giảng "tối ưu hóa sớm", tôi sẽ cung cấp cho bạn bài giảng "thay đổi hồ sơ để bạn có thể tự mình xem" bài giảng.
Tetrad

@Tetrad Tôi gần như xấu hổ khi thừa nhận rằng đây là một số lời khuyên khá tốt. Tôi chắc chắn nên làm hồ sơ nhiều hơn.
Lucius

1
Số hồ sơ là phiên bản gamedev của "bức ảnh hoặc nó đã không xảy ra" chắc chắn =)
Patrick Hughes

Câu trả lời:


3

Tôi thích cách tiếp cận trừu tượng được Hodgman vạch ra trong các chủ đề này trên gamedev.net:

Ông mô tả một hệ thống kết xuất ba lớp:

  1. API kết xuất cấp thấp chấp nhận "lệnh", trừu tượng hóa không nhiều hơn sự khác biệt giữa các API đồ họa khác nhau, chẳng hạn như Direct3D 9, Direct3D 11 và OpenGL. Mỗi "lệnh" ánh xạ tới một trạng thái hoặc lệnh gọi khác nhau, chẳng hạn như liên kết một luồng đỉnh hoặc kết cấu hoặc vẽ các nguyên hàm.
  2. API chấp nhận "kết xuất các mục", nhóm lại tất cả các trạng thái và một lệnh gọi rút thăm cần thiết để kết xuất một đối tượng nhất định, đồng thời sắp xếp và chuyển chúng thành các lệnh được gửi đến cấp độ đầu tiên. Một trạng thái kết xuất chứa một lệnh gọi rút thăm và một nhóm "nhóm trạng thái", nhóm này thay đổi trạng thái một cách hợp lý. Ví dụ: bạn có một nhóm trạng thái cho kết xuất kết xuất, một nhóm trạng thái cho vật liệu, một nhóm trạng thái cho hình học, ví dụ như một nhóm trạng thái, v.v. Cấp độ này chịu trách nhiệm sắp xếp các mục kết xuất này để giảm các thay đổi trạng thái dư thừa và loại bỏ mọi thay đổi trạng thái, trên thực tế, là dự phòng.
  3. Các hệ thống cấp cao như biểu đồ cảnh hoặc trình kết xuất GUI gửi các mục kết xuất đến cấp thứ hai. Điều quan trọng cần lưu ý là các hệ thống này không biết về thuật toán sắp xếp trạng thái hoặc API kết xuất cụ thể, khiến chúng hoàn toàn không dựa trên nền tảng. Chúng cũng dễ sử dụng một khi API cấp thấp hơn đã được triển khai.

Tóm lại, mô hình này giải quyết cả hai vấn đề của bạn cùng một lúc.

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.