Muy bien, estoy teniendo dificultades para empacar un bool y alinearlo en un búfer constante hlsl y no estoy seguro de por qué.
Aquí está el buffer en hlsl
cbuffer MaterialBuffer : register(b1) {
float3 materialDiffuseAlbedo;
float materialSpecularExponent;
float3 materialSpecularAlbedo;
bool isTextured;
};
Y aquí está en c ++
struct GeometryBufferPass_MaterialBuffer {
XMFLOAT3 diffuse;
float specularExponent;
XMFLOAT3 specular;
bool isTextured;
};
He intentado mover el bool y rellenar la estructura de muchas maneras sin suerte. ¿Cuál es la forma correcta de hacer esto?
directx
hlsl
data-structure
KlashnikovKid
fuente
fuente
Respuestas:
Para mayor eficiencia, los búferes constantes se asignarán de manera que los valores no se ubiquen en los registros de GPU . Cada registro tiene un tamaño de cuatro flotadores (16 bytes), por lo que las estructuras de búfer constantes deben ser un múltiplo de las mismas en la GPU. Su estructura C ++ debe rellenarse en consecuencia si desea usarla como una conveniencia para mapear datos (esto, nota, no siempre se escala bien).
Su problema, entonces, es que un booleano HLSL tiene cuatro bytes, pero un byte en el lado de la CPU (en su implementación específica). Esto hace que su estructura C ++ no se alinee correctamente: el bit significativo de un valor booleano (el 0 o 1 que importa) se almacenará en el byte menos significativo del valor, y dado que los tamaños no coinciden con la ubicación de ese byte en memoria diferirá en las versiones de CPU y GPU de la estructura.
Insertar manualmente el relleno apropiado y garantizar una alineación adecuada de 16 bytes, o simplemente usar un tipo de tamaño apropiado, como un entero, debería solucionar el problema. Este hilo también puede ser útil para usted, ya que contiene una discusión más profunda sobre aproximadamente el mismo problema.
fuente
isTextured
encaja en el mismo registro, ya que tendría que pasar a horcajadas en el siguiente. Por lo tanto, se incluye por completo en el siguiente registro". El segundo registro consistespecular
en los primeros tres componentes yisTextured
en el último, por lo que no veo que haya que meter nada en el siguiente registro. La longitud de bool de 1 byte frente a 4 byte obviamente importa, pero cualquiera de los dos encajaríaspecular
en el mismo registro.Bien, leí un poco y noté que un hlsl bool es esencialmente un entero de 32 bits. Así que solo usé un int en la estructura c ++ para resolver mi problema.
fuente
float, bool e int no se alinean necesariamente para endian, particularmente para artículos múltiples.
Cambiar a int o float funciona en algunos de los ejemplos enumerados aquí, ya que está alineado entre los elementos XMFLOAT3, por lo que se hace referencia correctamente. Sin embargo, si necesita declarar una matriz o varios elementos en la estructura para int, float (ninguno de los tipos XM), probablemente encontrará que los valores de GPU no coinciden con los valores establecidos en la estructura de la CPU.
Ciertamente lo hice al agregar una matriz de tipo int para usar para el tipo de iluminación.
La forma más fácil que encontré es apegarme a los tipos XM que se alinean en 16, lo que puede requerir elementos / bytes desperdiciados, pero clasifica el endian por usted. EG XMINT4 y acaba de usar el primer elemento .x para su valor, o si tiene la necesidad, use los otros elementos para otro propósito pero significa una mala denominación (asegúrese de comentar). Nota: la matriz XMINT2 también estará fuera de orden lógico
fuente