Я использую Directx10 в моей программе. Когда я пытаюсь изменить положение вершин, я получаю сообщение об ошибке:
Исключение выдается в 0x558CA083 (d3d10core.dll) в
NBodyProblemDebug.exe: 0xC0000005: расположение чтения нарушения доступа
0x00000000.
Это происходит во время выполнения следующего кода во время выполнения:
D3D10_MAPPED_TEXTURE3D resourse;
ZeroMemory(&resourse, sizeof(D3D10_MAPPED_TEXTURE3D));
g_pVertexBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &resourse.pData); //exception is thrown here
memcpy(resourse.pData, positions, 4 * n_bodies * sizeof(float));
g_pVertexBuffer->Unmap();
где буфер vektex инициализируется следующим образом:
float * positions;
ID3D10Buffer* g_pVertexBuffer = nullptr;
D3D10_BUFFER_DESC bd;
ZeroMemory( &bd, sizeof(bd) );
bd.Usage = D3D10_USAGE_DYNAMIC;
bd.ByteWidth = sizeof( SimpleVertex ) * bodies;
bd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
D3D10_SUBRESOURCE_DATA InitData;
ZeroMemory( &InitData, sizeof(InitData) );
InitData.pSysMem = positions;
result = m_device->CreateBuffer( &bd, &InitData, &g_pVertexBuffer );
Что нужно сделать, чтобы это исправить? Является ли этот код подходящим эквивалентом тому, который используется в Directx11:
D3D11_MAPPED_SUBRESOURCE resourse;
ZeroMemory(&resourse, sizeof(D3D11_MAPPED_SUBRESOURCE));
g_pImmediateContext->Map(g_pVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resourse);
memcpy(resourse.pData, positions, 4 * bodies * sizeof(float));
g_pImmediateContext->Unmap(g_pVertexBuffer, 0);
Ваш код не выполняет проверку ошибок. Всякий раз, когда COM API возвращает HRESULT
, вы должны проверить это на неудачу. Если было бы безопасно игнорировать возвращаемое значение, то оно вернуло бы void
, Вы должны использовать SUCCEEDED
или же FAILED
макросы, чтобы проверить результаты или принять что-то вроде ThrowIfFailed.
D3D11_MAPPED_SUBRESOURCE resource = {};
if ( SUCCEEDED(
g_pImmediateContext->Map(g_pVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD,
0, &resource) )
{
memcpy(resourse.pData, positions, 4 * bodies * sizeof(float));
g_pImmediateContext->Unmap(g_pVertexBuffer, 0);
}
Если, как вы заметили, исключение выдается на строку с Map
, то скорее всего вы пропустили неудачный HRESULT
ранее в программе, которая привела к g_pImmediateContext
все еще будучи nullptr.
Обратите внимание, что
ZeroMemory
очень старая школа Это необходимо только в том случае, если вы используете версию Visual C ++ до VS 2013. С VS 2013 или более поздней версии единые правила инициализации C ++ 11 означаютD3D11_MAPPED_SUBRESOURCE resource = {};
гарантированно заполняет структуру нулями.
Если однажды вы проверили все HRESULTs
где это уместно, вторым шагом для отладки приложения DirectX является включение устройства DEBUG. Затем в окне вывода отладки появятся дополнительные сведения о любых сбоях, которые помогут вам точно определить причину сбоя в вашей программе. Увидеть Анатомия Direct3D 11 Создать устройство а также Трюки с отладочным слоем Direct3D SDK
Кстати, в зависимости от вашего стиля вы используете сырые указатели для ваших интерфейсов COM. Вы должны рассмотреть вопрос о принятии смарт-указатель, как ComPtr.
Нет никаких причин продолжать использовать DirectX 10. Все поддерживаемые платформы, которые могут работать с DirectX 10, могут работать с DirectX 11. DirectX 11 поддерживает больше оборудования, имеет лучшую поддержку библиотек утилит, лучшую поддержку инструментов и является текущей «основной» версией DirectX. Не используйте DirectX 10. Перенос с DirectX 10 на DirectX 11 очень прост. Увидеть MSDN, Жизнь без D3DX, а также Развертывание Direct3D 11 для разработчиков игр
Других решений пока нет …