2

管理されていない DirectX 11 を初めて掘り下げました (ご容赦ください)。フォーラムで何度か質問されたにもかかわらず、まだ質問が残っているという問題があります。

オブジェクトが時間の経過とともにシーンに追加されるアプリとして開発しています。レンダリング ループごとに、シーン内のすべての頂点を収集し、パフォーマンスとベスト プラクティスのために、単一の頂点とインデックス バッファーを再利用してそれらをレンダリングしたいと考えています。私の質問は、動的頂点とインデックス バッファーの使用に関するものです。シーン コンテンツが変更されたときの正しい使用法を完全に理解できていません。

vertexBufferDescription.Usage               = D3D11_USAGE_DYNAMIC;
vertexBufferDescription.BindFlags           = D3D11_BIND_VERTEX_BUFFER;
vertexBufferDescription.CPUAccessFlags      = D3D11_CPU_ACCESS_WRITE;
vertexBufferDescription.MiscFlags           = 0;
vertexBufferDescription.StructureByteStride = 0;

シーンが初期化されたときにバッファを作成し、フレームごとにコンテンツを更新する必要がありますか? その場合、バッファの説明でどの ByteSize を設定すればよいですか? そして、私はそれを何で初期化しますか?

または、現在の頂点数をサイズとして使用して、シーンが最初にレンダリングされるとき (フレーム 1) に作成する必要がありますか? その場合、シーンに別のオブジェクトを追加するときに、バッファを再作成し、バッファ記述の ByteWidth を新しい頂点数に変更する必要はありませんか? シーンがフレームごとに頂点を更新し続ける場合、単一の動的バッファーを使用すると、このようにその目的が失われます...

シーンが初めてレンダリングされるときにバッファを初期化することをテストしており、それ以降は各フレームで Map/Unmap を使用しています。まず、ベクトル リストにすべてのシーン オブジェクトを入力し、次のようにリソースを更新します。

void Scene::Render() 
{
    (...)

    std::vector<VERTEX> totalVertices;
    std::vector<int> totalIndices;
    int totalVertexCount = 0;
    int totalIndexCount = 0;

    for (shapeIterator = models.begin(); shapeIterator != models.end(); ++shapeIterator)
    {
            Model* currentModel = (*shapeIterator);

            // totalVertices gets filled here...
    }

     // At this point totalVertices and totalIndices have all scene data

    if (isVertexBufferSet)
    {
        // This is where it copies the new vertices to the buffer.
        // but it's causing flickering in the entire screen...
        D3D11_MAPPED_SUBRESOURCE resource;
        context->Map(vertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource);
        memcpy(resource.pData, &totalVertices[0], sizeof(totalVertices));
        context->Unmap(vertexBuffer, 0);
    }
    else
    {
        // This is run in the first frame. But what if new vertices are added to the scene?
        vertexBufferDescription.ByteWidth = sizeof(VERTEX) * totalVertexCount;
        UINT stride = sizeof(VERTEX);
        UINT offset = 0;

        D3D11_SUBRESOURCE_DATA resourceData;
        ZeroMemory(&resourceData, sizeof(resourceData));
        resourceData.pSysMem = &totalVertices[0];

        device->CreateBuffer(&vertexBufferDescription, &resourceData, &vertexBuffer);
        context->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
        isVertexBufferSet = true;
    }

レンダリング ループの最後で、各オブジェクトの頂点のバッファー位置を追跡しながら、最後に Draw() を呼び出します。

    context->Draw(objectVertexCount, currentVertexOffset);
}

私の現在の実装では、シーン全体がちらつきます。しかし、メモリリークはありません。Map/Unmap API の使用方法と何か関係があるのでしょうか?

また、このシナリオでは、いつ buffer->Release() を呼び出すのが理想的でしょうか? ヒントやコードサンプルは素晴らしいでしょう! 前もって感謝します!

4

1 に答える 1

3

頂点バッファーへの memcpy で、次の操作を行います。

memcpy(resource.pData, &totalVertices[0], sizeof(totalVertices));

sizeof( totalVertices )あなたが望むものではない std::vector< VERTEX > のサイズを求めているだけです。

次のコードを試してください。

memcpy(resource.pData, &totalVertices[0], sizeof( VERTEX ) * totalVertices.size() );

IASetVertexBuffersまた、isVertexBufferSet が true の場合に呼び出すようには見えません。必ずそうしてください。

于 2013-03-21T13:16:31.860 に答える