Directx 10:使用CopySubresourceRegion更新顶点缓冲区

MJL*_*ala 0 c++ dynamic vertex-buffer directx-10

我有一个顶点缓冲区创建如下:

ID3D10Buffer * VertexBuffer;
Vertex_PosCol * Vertices;
D3D10_SUBRESOURCE_DATA VertexData;


    Vertices = new Vertex_PosCol[VerticeCount];

    Vertices[0].Position = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
    Vertices[0].Color = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f);

    Vertices[1].Position = D3DXVECTOR3(-1.0f, 2.0f, 0.0f);
    Vertices[1].Color = D3DXVECTOR4(1.0f, 0.0f, 0.0f, 1.0f);

    Vertices[2].Position = D3DXVECTOR3(1.0f, 2.0f, 0.0f);
    Vertices[2].Color = D3DXVECTOR4(0.0f, 1.0f, 0.0f, 1.0f);

    Vertices[3].Position = D3DXVECTOR3(2.0f, 1.0f, 0.0f);
    Vertices[3].Color = D3DXVECTOR4(0.0f, 0.0f, 1.0f, 1.0f);

    Vertices[4].Position = D3DXVECTOR3(2.0f, -1.0f, 0.0f);
    Vertices[4].Color = D3DXVECTOR4(1.0f, 1.0f, 0.0f, 1.0f);

    Vertices[5].Position = D3DXVECTOR3(1.0f, -2.0f, 0.0f);
    Vertices[5].Color = D3DXVECTOR4(0.0f, 1.0f, 1.0f, 1.0f);

    Vertices[6].Position = D3DXVECTOR3(-1.0f, -2.0f, 0.0f);
    Vertices[6].Color = D3DXVECTOR4(1.0f, 0.0f, 1.0f, 1.0f);

    Vertices[7].Position = D3DXVECTOR3(-2.0f, -1.0f, 0.0f);
    Vertices[7].Color = D3DXVECTOR4(1.0f, 0.0f, 0.0f, 1.0f);

    Vertices[8].Position = D3DXVECTOR3(-2.0f, 1.0f, 0.0f);
    Vertices[8].Color = D3DXVECTOR4(0.0f, 1.0f, 0.0f, 1.0f);

    D3D10_BUFFER_DESC vbd;
    vbd.Usage = D3D10_USAGE_DYNAMIC;
    vbd.ByteWidth = sizeof(Vertex_PosCol) * VerticeCount;
    vbd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
    vbd.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
    vbd.MiscFlags = 0;


    VertexData.pSysMem = Vertices;

    HRESULT result = this->GDM.Device->CreateBuffer(&vbd, &VertexData, &VertexBuffer);
Run Code Online (Sandbox Code Playgroud)

我目前正在使用ID3D10Buffer :: Map()更新我的顶点,现在工作正常.这个问题是我的应用程序将来可能需要大量的顶点更新,但不是每个网格/缓冲区中的每个顶点(一天,缓冲区将保存多个网格).据我所知,到处都说使用ID3D10Device :: CopySubresourceRegion().这正是我想要做的!除了我不能让它工作.我根本不明白它是如何工作的.我在上面阅读了微软的页面,并没有针对顶点缓冲区.我希望有人可以向我解释如何在顶点缓冲区方面实现它和/或将我链接到一些有用的资源来做同样的事情.

Iva*_*rop 12

你要问的是什么并不是很清楚,因为你不能用缓冲区来更新缓冲区ID3D10Device::CopySubresourceRegion().我想在我的答案中澄清资源复制和资源更新.

更新资源

通过"更新"资源,我们通常意味着通过覆盖将数据从系统存储器传输到GPU存储器1.要更新资源,请使用ID3D10Buffer::Map()/ ID3D10Buffer::Unmap()pair或ID3D10Device::UpdateSubresource()method.哪个更好用,取决于资源属性和更新频率(阅读Nvidia的"规范"论文).

用法非常简单.这是简单的1D缓冲区的情况,例如顶点缓冲区.

// Source array/vector (srcData): [xxxxDATADATADATADATADATAxxxxxxxxxxx]
//                                     ^                   ^
//                                 srcBegin        (srcBegin+bytesToCopy)
//
// Destination buffer (pBuffer):  [xxDATADATADATADATADATAxxxxxxxxxxxxx]  
//                                   ^                   ^
//                              destinationBegin  (destinationBegin+bytesToCopy)
D3D11_BOX box{};
box.left = destinationBegin;
box.right = destinationBegin + bytesToCopy;
box.top = 0;
box.bottom = 1;
box.front = 0;
box.back = 1;
Device->UpdateSubresource(pBuffer, 0, &box, (uint8_t*)srcData+srcBegin, 0, 0);
Run Code Online (Sandbox Code Playgroud)

复制资源

正如名称所述,ID3D10Device::CopySubresourceRegion()方法适用于在两个资源(例如缓冲区或纹理)之间复制数据.简化,您可以将其视为在视频卡的内存中复制数据块(但并非总是如此).您不能使用该方法"更新"GPU内存,因为数据已经被复制.

这是一个简单的例子:

D3D11_BOX srcBox{};
srcBox.left = srcBegin;
srcBox.right = srcBegin + size;
srcBox.top = 0;
srcBox.bottom = 1;
srcBox.front = 0;
srcBox.back = 1;
Device->CopySubresourceRegion(pDst, 0, dstBegin, 0, 0, pSrc, 0, &srcBox);
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你.

顺便说一下,2013年没有任何理由学习DirectX 10.你可以从DirectX 11开始,它的API几乎相同,但功能更多.


1这种解释过于简化.我们永远无法确定给定资源所在的位置(GPU,系统内存,无论存储),因为驱动程序实现者需要决定何时以及何种类型的资源存储.