DirectX12 CbvHeap


7

Với directX12 họ đã giới thiệu mô tả heap. Một cách để chúng tôi mô tả bảng cho các tài nguyên mà chúng tôi muốn gửi cho các shader. Tôi thừa nhận rất mới về đồ họa máy tính và chỉ sửa một chút trong directX11. Tôi chưa từng đùa giỡn với bất kỳ điều gì phức tạp hơn bây giờ vì vậy tôi có một đối tượng cho mọi lưới có những khuyết điểm này.

Microsoft::WRL::ComPtr<ID3D12Resource> mVertexBuffer;
D3D12_VERTEX_BUFFER_VIEW mVertexBufferView;

// Index Buffer
Microsoft::WRL::ComPtr<ID3D12Resource> mIndexBuffer;
D3D12_INDEX_BUFFER_VIEW mIndexBufferView;

// World View Projection Constant Buffer
Microsoft::WRL::ComPtr<ID3D12Resource> mWVPConstantBuffer;
WVPData mWVPData;      
UINT8* mMappedWVPBuffer;

// Directional Light Constant Buffer
Microsoft::WRL::ComPtr<ID3D12Resource> mDirLightConstantBuffer;
DirLightData mDirLightData;
UINT8* mMappedDirLightBuffer;

// CBVHeap
Microsoft::WRL::ComPtr<ID3D12DescriptorHeap> mCbvHeap;
UINT mCbvDescriptorSize;

Một bộ đệm đỉnh, bộ đệm chỉ mục, cbvHeap và hai bộ đệm không đổi. Một cho ma trận biến đổi và một cho dữ liệu ánh sáng định hướng.

Tôi không thực sự chắc chắn những gì cbvHeap (heap xem bộ đệm liên tục) thực sự đang làm. Tôi chỉ biết làm thế nào để sử dụng nó cho nội dung của tôi lên màn hình. Vì vậy, tôi đã thử nghiệm. Tôi lấy cbvHeap và mCbvDescriptorSize ra khỏi đối tượng mắt lưới và đặt nó vào đối tượng cảnh (nơi chứa các mảng lưới) và sau đó sử dụng cùng một cbvheap trên tất cả các mắt lưới của tôi. Điều này đã không hoạt động vì nó đã cho một màu nhất quán trên toàn bộ lưới. (tức là: Bộ đệm không đổi giống nhau được sử dụng cho mọi lưới cung cấp cho chúng cùng một dữ liệu ánh sáng khuếch tán và môi trường xung quanh.) Chính xác thì đống mô tả đã làm gì gây ra điều này? Và định nghĩa của tôi là đúng trên mỗi lưới?

Câu trả lời:


10

Trong DX12, một bộ mô tả là một bản ghi nhỏ, về cơ bản là một con trỏ, cho GPU biết nơi tìm một số dữ liệu như bộ đệm không đổi. Vì mỗi đối tượng sẽ có dữ liệu đệm không đổi riêng với các biến đổi riêng, thuộc tính vật liệu / ánh sáng, v.v., nên mỗi đối tượng cũng phải kết thúc bằng một bộ mô tả riêng để trỏ đến dữ liệu riêng của nó.

Có một số cách để thiết lập mô tả trong DX12. Đầu tiên, bạn có thể thêm các lệnh trong danh sách lệnh cập nhật mô tả trực tiếp trong bảng gốc. Ví dụ: bạn có thể sử dụng SetGraphicsRootConstantBufferView()để thiết lập các mô tả cho bộ đệm không đổi của đối tượng, sau đó vẽ đối tượng. Lặp lại cho nhiều đối tượng. Các mô tả này sẽ được lưu trong danh sách lệnh và sẽ được áp dụng theo thứ tự khi danh sách lệnh được thực thi trên GPU.

Cách khác để làm điều đó là sử dụng đống mô tả. Một đống mô tả về cơ bản là một bộ đệm lưu trữ một mảng các mô tả. Với phương pháp này, danh sách lệnh không lưu mô tả cho bạn; bạn phải tự quản lý chúng Nếu bạn ghi đè bất kỳ mô tả nào trước khi GPU tiêu thụ chúng, thì bạn sẽ nhận được kết quả sai. Điều này nghe có vẻ như những gì đang xảy ra trong chương trình của bạn: bạn có khả năng ghi đè cùng một bộ mô tả trong heap mỗi khi bạn đưa ra lệnh vẽ đối tượng trên CPU, do đó, khi GPU thực thi danh sách lệnh, chỉ có phần mô tả cuối cùng được viết ở đó, và mô tả đó được áp dụng cho tất cả các đối tượng.

Để khắc phục điều này, bạn phải phân bổ đủ không gian trong đống mô tả để lưu trữ tất cả các mô tả bạn sẽ sử dụng cho khung. Viết tất cả các mô tả của các đối tượng vào đống. Sau đó, khi vẽ từng đối tượng, trỏ shader vào dữ liệu của đối tượng đó bằng SetGraphicsRootDescriptorTable()một tay cầm bù trừ trỏ đến điểm trong heap nơi mô tả của đối tượng đó sống.

Miễn là bạn vẫn đang cố gắng học và chạy một ứng dụng đơn giản, có lẽ tôi sẽ gắn bó với cách tiếp cận bảng gốc càng nhiều càng tốt. Đối với một ứng dụng hiệu suất cao nghiêm trọng hơn, có thể có những tối ưu hóa bạn có thể thực hiện với đống mô tả, chẳng hạn như giữ tất cả các hằng số và kết cấu cho một vật liệu nhất định để bạn có thể tái sử dụng chúng trên nhiều đối tượng và liên kết tất cả chúng trong một cuộc gọi. Có lẽ bạn cũng muốn tránh việc có một bộ đệm và bộ mô tả liên tục cho mỗi đối tượng, mà là tổng hợp dữ liệu của nhiều đối tượng thành một vài bộ đệm lớn; Điều này sẽ hiệu quả hơn khi bạn có nhiều đối tượng.

Cũng đáng lưu ý rằng một ứng dụng 3D nghiêm túc sẽ muốn có nhiều danh sách lệnh của nhiều khung hình trong cùng một lúc, để có được sự song song của CPU / GPU và điều này sẽ đòi hỏi các bộ đệm và bộ mô tả liên tục được kéo dài để lưu trữ giá trị của nhiều khung hình Dữ liệu. Một lần nữa, đây là thứ bạn có thể đề cập đến cho mục đích học tập / mang lại bằng cách chỉ xây dựng một danh sách lệnh duy nhất tại một thời điểm, gửi nó và chờ đợi nó kết thúc trước khi chuyển sang khung tiếp theo.


Vấn đề với một trong hai phương thức (đặt địa chỉ GPU bộ đệm không đổi với SetGraphicsRootConstantBufferView () hoặc sử dụng tra cứu thứ cấp cho các mô tả trong bảng gốc) là nếu không có đủ địa chỉ GPU có sẵn để hiển thị tất cả các đối tượng thì nhà phát triển ứng dụng phải thực hiện chiến lược để thực hiện chiến lược sử dụng lại bộ nhớ đệm không đổi. Ứng dụng có thể phải đóng và gửi danh sách lệnh hiện tại (Đóng () rồi Đặt lại ()) có nghĩa là bạn phải sao chép trạng thái (PSO và trạng thái khác) vào danh sách lệnh mới. Làm thế nào để một ứng dụng sử dụng bộ nhớ đệm không đổi trong chiến lược bộ đệm vòng

Có vẻ như SE đã cắt bài đăng trong phần chuyển đổi để bình luận. Nó tiếp tục với "... y? Trước đây, các trình điều khiển sẽ nhận thấy không ghi đè được đặt hoặc đổi tên bộ nhớ nếu bộ nhớ trước đó bận. Làm thế nào để bạn thực hiện các chiến lược này trong DX12?"
Martin Ender
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.