Tudo bem, estou tendo dificuldade para obter um bool empacotado e alinhado em um buffer constante hlsl e não sei por que.
Aqui está o buffer em hlsl
cbuffer MaterialBuffer : register(b1) {
float3 materialDiffuseAlbedo;
float materialSpecularExponent;
float3 materialSpecularAlbedo;
bool isTextured;
};
E aqui está em c ++
struct GeometryBufferPass_MaterialBuffer {
XMFLOAT3 diffuse;
float specularExponent;
XMFLOAT3 specular;
bool isTextured;
};
Eu tentei mover o bool e preencher a estrutura de todos os tipos, sem sorte. Qual é a maneira correta de fazer isso?
directx
hlsl
data-structure
KlashnikovKid
fonte
fonte
Respostas:
Para eficiência, buffers constantes serão mapeados de forma que os valores não ultrapassem os registros da GPU . Cada registrador tem quatro flutuadores de tamanho (16 bytes); portanto, as estruturas de buffer constantes devem ser múltiplas na GPU. Sua estrutura C ++ deve ser preenchida de acordo, se você quiser usá-la como uma conveniência para mapear dados (isso, note, nem sempre é dimensionável).
Seu problema, então, é que um booleano HLSL tem quatro bytes, mas um byte no lado da CPU (em sua implementação específica). Isso faz com que sua estrutura C ++ não se alinhe corretamente: o bit significativo de um valor booleano (o 0 ou 1 que importa) será armazenado no byte menos significativo do valor, e como os tamanhos não concordam com a localização desse byte na memória será diferente nas versões de CPU e GPU da estrutura.
Inserir manualmente o preenchimento apropriado e garantir o alinhamento adequado de 16 bytes, ou apenas usar um tipo de tamanho apropriado, como um número inteiro, deve corrigir o problema. Esse tópico também pode ser útil para você, pois contém uma discussão mais aprofundada sobre o mesmo problema.
fonte
isTextured
encaixam-se no mesmo registro, pois ele teria que passar para o próximo. Assim, ele é colidido inteiramente com o próximo registro". O segundo registro consistespecular
nos três primeiros componentes eisTextured
no último, então não vejo que algo precise ser esbarrado no próximo registro? O comprimento do bool de 1 byte vs 4 bytes obviamente importa, mas qualquer um deles caberia depoisspecular
no mesmo registro.Tudo bem, fiz algumas leituras e percebi que um hlsl bool é essencialmente um número inteiro de 32 bits. Então, eu apenas usei um int na estrutura c ++ para resolver meu problema.
fonte
float, bool e int não são necessários para o endian, principalmente para vários itens.
Alternar para int ou float funciona em alguns dos exemplos listados aqui como alinhados entre os itens XMFLOAT3, portanto, são referenciados corretamente. No entanto, se você precisar declarar uma matriz ou vários itens na estrutura para int, float (nenhum tipo XM), provavelmente descobrirá que os valores da GPU não correspondem aos valores definidos na estrutura da CPU.
Certamente o fiz ao adicionar uma matriz do tipo int a ser usada para o tipo de iluminação.
A maneira mais fácil que encontrei é manter os tipos XM alinhados por 16, o que pode exigir elementos / bytes desperdiçados, mas classifica o endian para você. EG XMINT4 e acabou de usar o primeiro elemento .x para o seu valor, ou se você precisar, use os outros elementos para outra finalidade, mas significa má nomeação (certifique-se de comentar). Nota: A matriz XMINT2 também estará fora de ordem lógica
fonte