Краткое примечание
В настоящее время я работаю над дальнейшим анализом проблемы, чтобы дать более подробный и точный ответ.Я обновлю вопрос и ответ, чтобы отразить как можно большую точность, насколько я узнаю больше деталей.
Основной ответ
Точная проблема с вопросом выше (который был неизвестен навремя публикации), то, что буферы HLSL
не соответствуют их представлениям C#
;таким образом, переупорядочение переменных привело к сбою шейдера.Тем не менее, я все еще не уверен, почему, когда типы одинаковы.Я узнал о некоторых других вещах на своем пути для ответа и решил опубликовать их здесь.
Почему важен заказ
После некоторых дальнейших исследований и испытаний я все ещене уверен на 100% в том, что за причины этого одинаковы.В целом, я полагаю, это может быть связано с ожидаемыми типами в cbuffer
и порядком типов в struct
.В этом случае, если ваш cbuffer
ожидает сначала bool
, а затем float
, то перестановка вызывает проблемы.
cbuffer MaterialBuffer : register(b0) {
bool HasTexture;
float SpecularPower;
float4 Ambient;
...
}
// Won't work.
public struct MaterialBuffer {
public float SpecularPower;
public Vector2 padding2;
public bool HasTexture;
private bool padding0;
private short padding1;
public Color4 Ambient;
...
}
// Works.
public struct MaterialBuffer {
public bool HasTexture;
private bool padding0;
private short padding1;
public float SpecularPower;
public Vector2 padding2;
public Color4 Ambient;
...
}
Я приложил некоторые усилия для исследования различий в размере байтов типови это, похоже, ничего не меняет, но я опубликую свои выводы для общих базовых типов здесь:
1 Byte : bool, sbyte, byte
2 Bytes : short, ushort
4 Bytes : int, uint, float
8 Bytes : long, ulong, double
16 Bytes: decimal
Вы должны помнить об основных типах, используемых для создания более сложных типов,Например, у вас есть Vector2
со свойством X
и свойством Y
.Если они представлены типами float
, то вам потребуется 8-байтовый отступ до следующего свойства, если у вас нет других вещей, которые помогут достичь 16 байтов.Однако, если они представлены double
типами или decimal
типами, тогда размер будет другим, и вам нужно об этом знать.
Регистрация назначений
Iудалось решить проблему с реестром;это также соответствует стороне C#
при установке буферов.Когда вы устанавливаете буферы, вы назначаете индексы этим буферам, и HLSL
, как ожидается, будет использовать те же индексы.
// Buffer declarations in HLSL.
cbuffer ViewBuffer : register(b0)
cbuffer CameraBuffer : register(b1);
cbuffer MaterialBuffer : register(b2);
// Buffer assignments in C#.
context.VertexShader.SetConstantBuffer(0, viewBuffer);
context.VertexShader.SetConstantBuffer(1, cameraBuffer);
context.VertexShader.SetConstantBuffer(2, materialBuffer);
Приведенный выше код будет работать, как и ожидалось, поскольку буферы назначены на правильные регистры,Однако, если мы, например, изменим буфер для камеры на 8, тогда для правильной работы cbuffer
потребуется назначить регистр b8
.Код ниже не работает именно по этой причине.
cbuffer CameraBuffer : register(b1)
context.VertexShader.SetConstantBuffer(8, cameraBuffer);