Первоначально я использовал только одно объявление для одного набора буферов для астероида (куба) в моей игре. Он отлично работал.
Я хотел создать вектор буферов, чтобы отображать несколько астероидов. Когда я изменил объявления буферов на векторы, все ад сломался...
Компилятор не жалуется, но во время выполнения im получает:
Unhandled exception at 0x71879C01 (Msvcr110d.dll) in Game.exe: An invalid parameter was passed to a function that considers invalid parameters fatal.
Выходной журнал:
First-chance exception at 0x770D277C in Game.exe: Microsoft C++ exception: std::out_of_range at memory location 0x014A90CC.
The thread 0x8f4 has exited with code 0 (0x0).
First-chance exception at 0x770D277C in Game.exe: Microsoft C++ exception: [rethrow] at memory location 0x00000000.
First-chance exception at 0x770D277C in Game.exe: Microsoft C++ exception: std::out_of_range at memory location 0x014A9E10.
Unhandled exception at 0x712D9C01 (Msvcr110d.dll) in Game.exe: An invalid parameter was passed to a function that considers invalid parameters fatal.
Я так сказал свои буферы:
// Asteroid Buffers
vector<Microsoft::WRL::ComPtr<ID3D11Buffer>> asteroidVertexBuffers;
vector<Microsoft::WRL::ComPtr<ID3D11Buffer>> asteroidIndexBuffers;
vector<uint32> asteroidIndexCounts;
Я резервирую слот для трех буферов:
int asteroidCount = 3;
asteroidVertexBuffers.reserve( asteroidCount );
asteroidIndexBuffers.reserve( asteroidCount );
asteroidIndexCounts.reserve( asteroidCount );
Я повторяю и вставляю в вершину буферы:
for( int a = 0; a < asteroidCount; a++ )
{
D3D11_SUBRESOURCE_DATA asteroidVertexBufferData = {0};
asteroidVertexBufferData.pSysMem = asteroidVertices;
asteroidVertexBufferData.SysMemPitch = 0;
asteroidVertexBufferData.SysMemSlicePitch = 0;
CD3D11_BUFFER_DESC asteroidVertexBufferDesc(sizeof(asteroidVertices), D3D11_BIND_VERTEX_BUFFER);
DX::ThrowIfFailed(
m_d3dDevice->CreateBuffer(
&asteroidVertexBufferDesc,
&asteroidVertexBufferData,
&asteroidVertexBuffers.at( a )
)
);
// Runtime Crash here
asteroidIndexCounts.at( a ) = ARRAYSIZE(asteroidIndices);
D3D11_SUBRESOURCE_DATA asteroidIndexBufferData = {0};
asteroidIndexBufferData.pSysMem = asteroidIndices;
asteroidIndexBufferData.SysMemPitch = 0;
asteroidIndexBufferData.SysMemSlicePitch = 0;
CD3D11_BUFFER_DESC asteroidIndexBufferDesc(sizeof(asteroidIndices), D3D11_BIND_INDEX_BUFFER);
DX::ThrowIfFailed(
m_d3dDevice->CreateBuffer(
&asteroidIndexBufferDesc,
&asteroidIndexBufferData,
&asteroidIndexBuffers.at( a )
)
);
}
Заметки, которые могут быть полезны
Обновление: думаю, я нашел проблему (& в память, которая перераспределена)
Думаю, я нашел проблему. Я только заметил, что _IN на первом и втором параметрах, что ссылка на память, а это значит, что она тоже должна быть вектором памяти... Я исправлю и посмотрю, работает ли она тогда.
Обновление :: Я был неправ, или я делаю это неправильно...
Я добавил еще несколько векторов для новых типов, а затем ввел все это в свой код:
int asteroidCount = 3;
asteroidVertexBuffersData.reserve( asteroidCount );
asteroidVertexBuffersDesc.reserve( asteroidCount );
asteroidVertexBuffers.reserve( asteroidCount );
asteroidIndexBuffers.reserve( asteroidCount );
asteroidIndexCounts.reserve( asteroidCount );
for( int a = 0; a < asteroidCount; a++ )
{
D3D11_SUBRESOURCE_DATA asteroidVertexBufferData = {0};
asteroidVertexBuffersData.push_back( asteroidVertexBufferData );
asteroidVertexBuffersData.at(a).pSysMem = asteroidVertices;
asteroidVertexBuffersData.at(a).SysMemPitch = 0;
asteroidVertexBuffersData.at(a).SysMemSlicePitch = 0;
CD3D11_BUFFER_DESC asteroidVertexBufferDesc(sizeof(asteroidVertices), D3D11_BIND_VERTEX_BUFFER);
asteroidVertexBuffersDesc.push_back( asteroidVertexBufferDesc );
DX::ThrowIfFailed(
m_d3dDevice->CreateBuffer(
&asteroidVertexBuffersDesc.at(a),
&asteroidVertexBuffersData.at(a),
&asteroidVertexBuffers.at(a)
)
);
Он выдает ту же ошибку: '(
Обновление :: Я прошел процесс отказа и нашел следующие интересные бит и бобы
pszFunction содержит:
std::vector<class Microsoft::WRL::ComPtr<struct ID3D11Buffer>,class std::allocator<class Microsoft::WRL::ComPtr<struct ID3D11Buffer> > >::operator []
изменить размер вместо резерва:
int asteroidCount = 3;
asteroidVertexBuffers.resize( asteroidCount );
asteroidIndexBuffers.resize( asteroidCount );
asteroidIndexCounts.resize( asteroidCount );
Тип возвращаемого значения vector :: at() - это ССЫЛКА. Поэтому я думаю, что вам нужно просто использовать "asteroidVertexBuffers.at(a)" в качестве третьего параметра метода "CreateBuffer".
Не зная, какую версию Direct3D вы используете или как вы создаете устройство, и поэтому трудно понять, где вы ошибаетесь. Возможно, что один из других параметров неверен и вызывает ошибку.
Вы не хотите ссылаться на элемент в векторе, который вам нужен, поскольку третий параметр ожидает ID3D11Buffer**
который является указателем на указатель.
Вот небольшой пример, который работает. Если ваше использование отличается от других, отредактируйте этот вопрос, включив в него небольшой самостоятельный пример, чтобы мы могли видеть достаточно, чтобы дать вам хороший ответ.
#include <Windows.h>
#include <d3d11.h>
#include <DirectXMath.h>
#include <iostream>
#include <vector>
using DirectX::XMFLOAT3;
#pragma comment(lib, "d3d11.lib")
int main()
{
ID3D11Device* device = NULL;
if(FAILED(D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &device, NULL, NULL)))
{
std::cerr << "Device creation Failed!\n";
return 0;
}
struct SimpleVertexCombined
{
XMFLOAT3 Pos;
XMFLOAT3 Col;
};
SimpleVertexCombined verticesCombo[] =
{
XMFLOAT3(0.0f, 0.5f, 0.5f),
XMFLOAT3(0.0f, 0.0f, 0.5f),
XMFLOAT3(0.5f, -0.5f, 0.5f),
XMFLOAT3(0.5f, 0.0f, 0.0f),
XMFLOAT3(-0.5f, -0.5f, 0.5f),
XMFLOAT3(0.0f, 0.5f, 0.0f),
};
D3D11_BUFFER_DESC bufferDesc;
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
bufferDesc.ByteWidth = sizeof(SimpleVertexCombined)* 3;
bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bufferDesc.CPUAccessFlags = 0;
bufferDesc.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA InitData;
InitData.pSysMem = verticesCombo;
InitData.SysMemPitch = 0;
InitData.SysMemSlicePitch = 0;
std::vector<ID3D11Buffer*> VertexBuffers(1);
HRESULT hr = device->CreateBuffer(&bufferDesc, &InitData, &VertexBuffers[0]);
if(SUCCEEDED(hr))
{
std::cout << "CreateBuffer Success! - Buffer = 0x" << VertexBuffers[0] << "\n";
}
else
{
std::cout << "CreateBuffer Failure!\n";
}
return 0;
}