DirectXTK: интегрировать файл hlsl в модель и систему эффектов
Запрограммировав для OpenGL ES и XNA некоторое время, я теперь обновляю часть своего контента до DirectXTK для XBOX One. К сожалению, я просто столкнулся с другой проблемой - а именно с интеграцией пользовательских шейдерных файлов.
В частности, у меня есть следующий вершинный шейдер:
cbuffer ModelViewProjectionConstantBuffer : register(b0)
{
matrix model;
matrix view;
matrix projection;
};
struct VertexShaderInput
{
float3 pos : POSITION;
};
struct PixelShaderInput
{
float4 pos : SV_POSITION;
};
PixelShaderInput main(VertexShaderInput input)
{
PixelShaderInput output;
float4 pos = float4(input.pos, 1.0f);
pos = mul(pos, model);
pos = mul(pos, view);
pos = mul(pos, projection);
output.pos = pos;
return output;
}
Загрузка его в реализацию IEffectFactory прекрасно работает до сих пор. На первом этапе я использую LoadAsync для загрузки скомпилированного файла hlsl:
void SUS3DApp1Main::SUSCreateDeviceResources()
{
auto loadVSTask = DX::ReadDataAsync(L"SampleVertexShader.cso");
auto loadPSTask = DX::ReadDataAsync(L"SamplePixelShader.cso");
auto createVSTask = loadVSTask.then([this](const std::vector<byte>& fileData) {
DX::ThrowIfFailed(
m_deviceResources->GetD3DDevice()->CreateVertexShader(
&fileData[0],
fileData.size(),
nullptr,
&myVertexShader
)
);
myVShaderCode = fileData.data();
myVShaderCodeSize = fileData.size();
myFlagVSUp = true;
}); //VS hoch
...
Затем две переменные myVShaderCode и mVShaderCodeSize передаются в фактическую реализацию iEffect, которая использует их следующим образом:
void SUS3DApp1::SUSEffect::GetVertexShaderBytecode(void const ** pShaderByteCode, size_t * pByteCodeLength)
{
(*pByteCodeLength) = myVShaderCodeSize;
(*pShaderByteCode) = myVShaderCode;
}
К сожалению, это не работает во время выполнения. Вместо этого ошибка типа необработанного исключения в 0x603520B5 (ucrtbased.dll) в SUS3DApp1.exe: недопустимый параметр был передан функции, которая считает недопустимые параметры фатальными. брошен Стек вызовов выглядит так:
> SUS3DApp1.exe!DirectX::ThrowIfFailed(HRESULT hr) Line 48 C++
SUS3DApp1.exe!CreateInputLayout(ID3D11Device * device, DirectX::IEffect * effect, ID3D11InputLayout * * pInputLayout, bool skinning) Line 202 C++
SUS3DApp1.exe!DirectX::Model::CreateFromCMO(ID3D11Device * d3dDevice, const unsigned char * meshData, unsigned int dataSize, DirectX::IEffectFactory & fxFactory, bool ccw, bool pmalpha) Line 796 C++
SUS3DApp1.exe!DirectX::Model::CreateFromCMO(ID3D11Device * d3dDevice, const wchar_t * szFileName, DirectX::IEffectFactory & fxFactory, bool ccw, bool pmalpha) Line 848 C++
SUS3DApp1.exe!SUSModel::SUSModel(ID3D11Device * _dev, std::basic_string<char,std::char_traits<char>,std::allocator<char> > & resource, const unsigned char * _myVShaderCode, int _myVShaderCodeSize) Line 15 C++
SUS3DApp1.exe!SUS3DApp1::SUS3DApp1Main::SetUpShaderDependentResources() Line 62 C++
SUS3DApp1.exe!SUS3DApp1::SUS3DApp1Main::Render() Line 148 C++
Идеи, кто-нибудь? Я уже проверил действительность переменных-членов в GetVertexShaderBytecode...
Обновление: теперь я изменил шейдер, а также загрузку кода. Странно, но эта часть кода теперь проходит этап CreateInputLayout внутри SUSCreateDeviceResources: void SUS3DApp1Main::SUSCreateDeviceResources() { auto loadVSTask = DX::ReadDataAsync(L"SampleVertexShader.cso"); auto loadPSTask = DX::ReadDataAsync(L"SamplePixelShader.cso");
auto createVSTask = loadVSTask.then([this](const std::vector<byte>& fileData) {
DX::ThrowIfFailed(
m_deviceResources->GetD3DDevice()->CreateVertexShader(
&fileData[0],
fileData.size(),
nullptr,
&myVertexShader
)
);
myVShaderCode = &fileData[0];
myVShaderCodeSize = fileData.size();
Microsoft::WRL::ComPtr<ID3D11InputLayout> il;
DX::ThrowIfFailed(
m_deviceResources->GetD3DDevice()->CreateInputLayout(VertexPositionNormal::InputElements,
VertexPositionNormal::InputElementCount,
myVShaderCode, myVShaderCodeSize,
&il)
);
myFlagVSUp = true;
}); //VS hoch
Проблема возникает при создании модели, где она снова является недопустимым параметром. Это очень странно, так как создание работало хорошо раньше. Может быть, значение myVShaderCode потеряно?