Pergunta

I was originally just using a single declaration for 1 set of buffers for an asteroid(cube) in my game. It worked great.

I wanted to create a vector of buffers in order to display multiple asteroids. When I changed the declarations of the buffers to vectors, all hell broke loose...

The compiler does not complain but on run time im getting:

Unhandled exception at 0x71879C01 (Msvcr110d.dll) in Game.exe: An invalid parameter was passed to a function that considers invalid parameters fatal.

Output log:

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.

I have declared my buffers like so:

// Asteroid Buffers 
vector<Microsoft::WRL::ComPtr<ID3D11Buffer>> asteroidVertexBuffers;
vector<Microsoft::WRL::ComPtr<ID3D11Buffer>> asteroidIndexBuffers;
vector<uint32> asteroidIndexCounts;

I reserve a slot for three buffers:

int asteroidCount = 3;

asteroidVertexBuffers.reserve( asteroidCount );
asteroidIndexBuffers.reserve( asteroidCount );
asteroidIndexCounts.reserve( asteroidCount );

I iterate and push into the vertex the buffers:

    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 )
                )
            );
    }

Notes that might be helpful


Update: Think I found the issue ( & to memory that is re-allocated )

Think I found the issue. I just noticed that the _IN on the first and second parameter that's the reference of the memory and it means it needs to be a vector of memory too... I'll correct and see if it then works.

Update:: I was wrong or I am doing it wrong...

I added some more vectors for the new types and then inserted it all into my code:

    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)
                )
            );

It throws the same error :'(

Update:: I walked through the failure process and found the following interesting bits and bobs

enter image description here

pszFunction contains:

   std::vector<class Microsoft::WRL::ComPtr<struct ID3D11Buffer>,class std::allocator<class Microsoft::WRL::ComPtr<struct ID3D11Buffer> > >::operator []

Foi útil?

Solução 3

resize instead of reserve:

    int asteroidCount = 3;

    asteroidVertexBuffers.resize( asteroidCount );
    asteroidIndexBuffers.resize( asteroidCount );
    asteroidIndexCounts.resize( asteroidCount );

Outras dicas

Without knowing which Direct3D version you're using or how you create the device and such it's hard to know where you're going wrong. It's possible one of the other parameters is incorrect and causing the error.

You don't want a reference to an item in the vector you want its address since the 3rd parameter expects an ID3D11Buffer** which is a pointer to a pointer.

Here's a small example that works. If your usage is different please edit the question to include a small self contained example like this so we can see enough to give you a good answer.

#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;
}

The type of the return value of vector::at() is REFERENCE itself. So I think you should just use "asteroidVertexBuffers.at(a)" as the third parameter of method "CreateBuffer".

see: http://www.cplusplus.com/reference/vector/vector/at/

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top