Tại sao tôi không thể có được một bool được đóng gói và căn chỉnh vào bộ đệm không đổi D3D?


9

Được rồi, tôi đang có một thời gian khó khăn để có được một bool đóng gói và liên kết vào một bộ đệm liên tục hlsl và tôi không chắc tại sao.

Đây là bộ đệm trong hlsl

cbuffer MaterialBuffer : register(b1) {
    float3 materialDiffuseAlbedo;
    float  materialSpecularExponent;
    float3 materialSpecularAlbedo;
    bool isTextured;
};

Và đây là trong c ++

struct GeometryBufferPass_MaterialBuffer {
    XMFLOAT3 diffuse;
    float specularExponent;
    XMFLOAT3 specular;
    bool isTextured;
};

Tôi đã thử di chuyển bool và đệm cấu trúc theo mọi cách mà không gặp may. cách chính xác để làm điều này là gì?


Vấn đề nó gây ra là gì?
MichaelHouse

Bool được sử dụng để xác định xem shader có cần lấy mẫu kết cấu hay không. Bằng cách này, tôi có thể kết xuất các đối tượng có kết cấu và không có kết cấu với cùng một shader. Bool chỉ đơn giản được sử dụng trong một tuyên bố có điều kiện. Nó không nhận được dữ liệu chính xác vì nó đối xử với tất cả các đối tượng như nhau. Điều này là không chính xác bởi vì quả cầu bầu trời của tôi là thứ duy nhất có kết cấu tại thời điểm này.
KlashnikovKid

Các giá trị khác hoạt động nhưng không phải là bool? Bạn đã thử sử dụng một trong những trình gỡ lỗi có sẵn cho các shader để xem những gì được đưa vào nó chưa?
MichaelHouse

2
cố gắng lưu trữ giá trị bool trong một char. lưu trữ là 1 cho đúng và 0 cho sai. Chỉ để thử nghiệm, và cũng vậy, một bool là 1 byte trong C ++ dù sao ...
Gustavo Maciel

3
Kích thước của một bool là phụ thuộc thực hiện. Trên một số nền tảng, nó có cùng kích thước với một int. stackoverflow.com/questions/5067492/ từ
Tetrad

Câu trả lời:


9

Để hiệu quả, các bộ đệm liên tục sẽ được ánh xạ sao cho các giá trị không làm căng các thanh ghi GPU . Mỗi thanh ghi có bốn phao có kích thước (16 byte) vì vậy các cấu trúc bộ đệm không đổi phải là bội số của chúng trên GPU. Cấu trúc C ++ của bạn phải được đệm phù hợp nếu bạn muốn sử dụng nó để thuận tiện cho việc ánh xạ dữ liệu (điều này, lưu ý, không phải lúc nào cũng có tỷ lệ tốt).

Sau đó, vấn đề của bạn là boolean HLSL có bốn byte, nhưng một byte ở phía CPU (trong triển khai cụ thể của bạn). Điều này khiến cấu trúc C ++ của bạn không căn chỉnh chính xác: bit đáng kể của giá trị boolean (0 hoặc 1 có vấn đề) sẽ được lưu trữ trong byte có giá trị nhỏ nhất của giá trị và vì kích thước không đồng ý với vị trí của byte đó trong bộ nhớ sẽ khác nhau trong các phiên bản cấu trúc CPU và GPU.

Chèn thủ công phần đệm thích hợp và đảm bảo căn chỉnh 16 byte thích hợp hoặc chỉ sử dụng loại có kích thước phù hợp, như số nguyên, sẽ khắc phục vấn đề. Chủ đề này cũng có thể được sử dụng cho bạn vì nó chứa một cuộc thảo luận sâu hơn về cùng một vấn đề.


1
Tôi không tuân theo: " isTexturedphù hợp với cùng một thanh ghi vì nó sẽ phải đi vào thanh tiếp theo. Do đó, nó được chuyển hoàn toàn vào thanh ghi tiếp theo." Thanh ghi thứ hai bao gồm speculartrong ba thành phần đầu tiên và isTexturedcuối cùng, vì vậy tôi không thấy rằng bất cứ điều gì cần phải được đưa vào đăng ký tiếp theo? Độ dài bool 1 byte so với 4 byte rõ ràng là có vấn đề, nhưng một trong hai sẽ phù hợp sau speculartrong cùng một thanh ghi.
Nathan Reed

Bạn nói đúng; Tôi nhầm lẫn bản thân mình với kích thước của các thanh ghi so với kích thước của các loại và đưa ra một biểu diễn không chính xác của ánh xạ. Vấn đề duy nhất là vị trí của byte có liên quan trong bộ nhớ. Tôi đã điều chỉnh câu trả lời của mình cho phù hợp.

Chấp nhận câu trả lời của bạn cho sự thấu đáo. Giống như bạn đã đề cập, đó là một vấn đề lớn / nhỏ về cuối và sử dụng một int đã giải quyết nó.
KlashnikovKid

3

Được rồi, đã đọc và nhận thấy rằng một bool hlsl về cơ bản là một số nguyên 32 bit. Vì vậy, tôi chỉ sử dụng một int trong cấu trúc c ++ để giải quyết vấn đề của mình.

struct GeometryBufferPass_MaterialBuffer {
    XMFLOAT3 diffuse;
    float specularExponent;
    XMFLOAT3 specular;
    int isTextured;
};

Tại sao bạn không giữ kiểu bool mà chỉ sử dụng int trong phía trình biên dịch? Chỉ để giữ ngữ nghĩa.
Gustavo Maciel

Vâng, đó là những gì tôi đang làm ở trên. Đã sử dụng một số nguyên cho phía cpu struct và bool cho phía gpu đệm không đổi.
KlashnikovKid

0

float, bool và int không cần thiết xếp hàng cho endian đặc biệt cho nhiều mục.

Chuyển sang int hoặc float hoạt động trong một số ví dụ được liệt kê ở đây vì nó được căn chỉnh giữa các mục XMFLOAT3 để được tham chiếu chính xác. Tuy nhiên, nếu bạn cần khai báo một mảng hoặc một vài mục trong cấu trúc cho int, float (không có loại XM) thì có thể bạn sẽ thấy rằng các giá trị GPU không khớp với các giá trị được đặt trong cấu trúc CPU.

Tôi chắc chắn đã làm khi thêm một mảng kiểu int được sử dụng cho kiểu chiếu sáng.

Cách dễ nhất tôi tìm thấy là bám vào các loại XM thẳng hàng với 16, có thể yêu cầu các phần tử / byte bị lãng phí nhưng sắp xếp endian cho bạn. EG XMINT4 và chỉ sử dụng phần tử đầu tiên .x cho giá trị của bạn hoặc nếu bạn có nhu cầu thì hãy sử dụng các phần tử khác cho mục đích khác nhưng có nghĩa là đặt tên kém (đảm bảo nhận xét). Lưu ý: mảng XMINT2 cũng sẽ không theo thứ tự logic

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.