D'accord, j'ai du mal à obtenir un bool emballé et aligné dans un tampon constant hlsl et je ne sais pas pourquoi.
Voici le tampon en hlsl
cbuffer MaterialBuffer : register(b1) {
float3 materialDiffuseAlbedo;
float materialSpecularExponent;
float3 materialSpecularAlbedo;
bool isTextured;
};
Et le voici en c ++
struct GeometryBufferPass_MaterialBuffer {
XMFLOAT3 diffuse;
float specularExponent;
XMFLOAT3 specular;
bool isTextured;
};
J'ai essayé de déplacer le booléen et de remplir la structure de toutes sortes de façons sans succès. Quelle est la bonne façon de procéder?
directx
hlsl
data-structure
KlashnikovKid
la source
la source
Réponses:
Pour plus d'efficacité, les tampons constants seront mappés de telle sorte que les valeurs ne chevauchent pas les registres GPU . Chaque registre a une taille de quatre flottants (16 octets), donc les structures de tampon constantes doivent être un multiple de celui-ci sur le GPU. Votre structure C ++ doit être complétée en conséquence si vous souhaitez l'utiliser comme commodité pour mapper des données (cela, notez-le, n'est pas toujours bien mis à l'échelle).
Votre problème est donc qu'un booléen HLSL fait quatre octets, mais un octet côté CPU (dans votre implémentation spécifique). Cela provoque que votre structure C ++ ne s'aligne pas correctement: le bit significatif d'une valeur booléenne (le 0 ou 1 qui importe) va être stocké dans l'octet le moins significatif de la valeur, et puisque les tailles ne correspondent pas à l'emplacement de cet octet en mémoire sera différent dans les versions CPU et GPU de la structure.
L'insertion manuelle du remplissage approprié et la garantie d'un alignement correct sur 16 octets, ou tout simplement en utilisant un type de taille appropriée, comme un entier, devraient résoudre le problème. Ce fil peut également vous être utile car il contient une discussion plus approfondie sur à peu près le même problème.
la source
isTextured
rentre dans ce même registre car il devrait chevaucher dans le suivant. Ainsi, il est entièrement transféré dans le registre suivant." Le deuxième registre se compose desspecular
trois premiers composants etisTextured
du dernier, donc je ne vois pas quoi que ce soit doit être heurté dans le prochain registre? La longueur booléenne 1 octet vs 4 octets importe évidemment, mais l'un ou l'autre s'inscrirait ensuitespecular
dans le même registre.D'accord, j'ai lu un peu et remarqué qu'un booléen hlsl est essentiellement un entier 32 bits. J'ai donc utilisé un int dans la structure c ++ pour résoudre mon problème.
la source
float, bool et int ne sont pas nécessairement alignés pour endian, en particulier pour plusieurs éléments.
Le passage à int ou float fonctionne dans certains des exemples répertoriés ici car il est aligné entre les éléments XMFLOAT3 et sont donc référencés correctement. Cependant, si vous devez déclarer un tableau ou plusieurs éléments dans la structure pour int, float (aucun type XM), vous constaterez probablement que les valeurs GPU ne correspondent pas aux valeurs définies dans la structure CPU.
Je l'ai certainement fait lors de l'ajout d'un tableau de type int à utiliser pour le type d'éclairage.
Le moyen le plus simple que j'ai trouvé est de s'en tenir aux types XM qui s'alignent par 16, ce qui peut nécessiter des éléments / octets gaspillés mais trie l'endian pour vous. EG XMINT4 et juste utilisé le premier élément .x pour votre valeur, ou si vous en avez besoin, utilisez les autres éléments dans un autre but mais signifie une mauvaise dénomination (assurez-vous de commenter). Remarque: le tableau XMINT2 sera également hors de l'ordre logique
la source