Neden D3D sabit tamponuna paketlenmiş ve hizalanmış bir bool alamıyorum?


9

Pekala, paketlenmiş ve hlsl sabit tamponuna hizalanmış bir bool almakta zorlanıyorum ve neden olduğundan emin değilim.

İşte hlsl'deki tampon

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

Ve burada c ++ 'da

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

Bool'u hareket ettirmeyi ve yapıyı her türlü şekilde şanssız doldurmayı denedim. Bunu yapmanın doğru yolu nedir?


Soruna neden olan nedir?
MichaelHouse

Bool, gölgelendiricinin bir doku örneklemesi gerekip gerekmediğini belirlemek için kullanılır. Bu şekilde, aynı gölgelendirici ile dokulu ve dokusuz nesneleri oluşturabilirim. Bool sadece koşullu bir ifadede kullanılır. Doğru verileri alamıyor çünkü tüm nesnelere aynı şekilde davranıyor. Bu yanlış çünkü şu anda bir dokuya sahip olan tek şey gökyüzü kürem.
KlashnikovKid

Diğer değerler çalışıyor ama bool değil mi? Gölgelendiricilerin içine ne girdiğini görmek için hata ayıklayıcılardan birini kullanmayı denediniz mi?
MichaelHouse

2
bool değerini bir karakterde depolamaya çalışın. true için 1 ve false için 0 olarak saklayın. Sadece test için ve ayrıca, bir bool C ++ 'da 1 bayttır ...
Gustavo Maciel

3
Bir boolun boyutu uygulamaya bağlıdır. Bazı platformlarda int ile aynı boyuttadır. stackoverflow.com/questions/5067492/…
Tetrad

Yanıtlar:


9

Verimlilik için sabit tamponlar, değerler GPU kayıtlarını engellemeyecek şekilde eşlenir . Her kayıt dört boyuttadır (16 bayt), bu nedenle sabit tampon yapıları GPU'da bunun bir katı olmalıdır. Verileri haritalamak için kolaylık olarak kullanmak istiyorsanız, C ++ yapınız buna göre doldurulmalıdır (bu, not her zaman iyi ölçeklenmez).

O halde sorununuz, HLSL booleanının dört bayt, ancak CPU tarafında bir bayt olmasıdır (özel uygulamanızda). Bu, C ++ yapınızın düzgün hizalanmamasına neden olur: bir boolean değerinin (0 veya 1 önemli değeri) önemli biti, değerin en az önemli baytında saklanır ve boyutlar konumu kabul etmez. bellekteki baytın yapısı yapının CPU ve GPU sürümlerinde farklılık gösterir.

Uygun dolguyu elle yerleştirme ve uygun 16 baytlık hizalama sağlama veya yalnızca tamsayı gibi uygun boyutta bir tür kullanma sorunu çözmelidir. Bu konu , kabaca aynı sorunun daha ayrıntılı bir tartışmasını içerdiğinden sizin için de yararlı olabilir.


1
Ben takip etmiyorum: " isTexturedaynı kayıt defterine sığdır çünkü bir sonraki kayıt defterine binmek zorunda kalacak. Bu yüzden tamamen bir sonraki kayıt defterine çarptı." İkinci kayıt specularilk üç bileşen ve isTexturedson olarak oluşur, bu yüzden bir şey sonraki kayıt çarpmak gerektiğini görmüyorum? 1 bayt ve 4 bayt bool uzunluğu açıkça önemlidir, ancak her ikisi specularde aynı kayıt defterine sığar .
Nathan Reed

Haklısın; Kayıtların büyüklüğüne ve türlerin boyutuna göre kendimi karıştırdım ve eşlemenin yanlış bir gösterimi ile geldim. Tek sorun, ilgili baytın bellekteki konumudur. Cevabımı buna göre ayarladım.

Cevabınızı titizlikle kabul etmek. Bahsettiğiniz gibi, bu büyük / küçük bir endian meselesiydi ve bir int kullanmak sorunu çözdü.
KlashnikovKid

3

Tamam, biraz okuma yaptı ve bir hlsl boolunun aslında 32 bitlik bir tam sayı olduğunu fark etti. Bu yüzden sadece sorunumu çözmek için c ++ yapısında bir int kullandım.

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

Neden bool tipini tutmuyorsunuz ancak derleyici tarafında int kullanıyorsunuz? Anlambilimi korumak için.
Gustavo Maciel

Evet, yukarıda yaptığım şey bu. Yapı cpu tarafı için bir tamsayı ve sabit tampon gpu tarafı için bir bool kullanıldı.
KlashnikovKid

0

şamandıra, bool ve int özellikle birden fazla öğe için endian için sıraya girmez.

İnt veya float'a geçiş, burada listelenen örneklerin bazılarında XMFLOAT3 öğeleri arasında hizalandığı için çalışır; Ancak int, float (none XM type) için yapıda bir dizi veya birkaç öğe bildirmeniz gerekiyorsa, GPU değerlerinin CPU yapısında ayarlanan değerlerle eşleşmediğini göreceksiniz.

Kesinlikle aydınlatma türü için kullanılacak bir tür int eklerken yaptım.

Bulduğum en kolay yol, boşa giden elemanlar / bayt gerektirebilecek ancak endianı sizin için sıralayan 16 ile hizalanan XM tiplerine bağlı kalmaktır. EG XMINT4 ve sadece değeriniz için ilk öğe .x'i kullandı veya ihtiyacınız varsa diğer öğeleri başka bir amaç için kullanın, ancak kötü adlandırma anlamına gelir (yorum yaptığınızdan emin olun). Not: XMINT2 dizisi de mantıksal sırada olmayacak

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.