我创建了一个顶点缓冲区,如下所示:
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);
我目前正在使用ID3D10Buffer :: Map()更新我的顶点,现在工作正常。这个问题是我的应用程序将来可能需要大量的顶点更新,但不是每个网格/缓冲区中的每个顶点(一天,缓冲区将保存多个网格)。据我所知,到处都说使用ID3D10Device :: CopySubresourceRegion()。这正是我想要做的!除了我不能让它工作。我根本不明白它是如何工作的。我在上面阅读了微软的页面,并没有针对顶点缓冲区。我希望有人可以向我解释如何在顶点缓冲区方面实现它和/或将我链接到一些有用的资源来做同样的事情。
答案 0 :(得分:11)
您要问的是什么并不十分清楚,因为您无法使用ID3D10Device::CopySubresourceRegion()
更新缓冲区。我想在答案中澄清资源复制和资源更新。
通过“更新”资源,我们通常意味着将数据从系统内存传输到GPU内存 1 ,并进行覆盖。
要更新资源,请使用ID3D10Buffer::Map()
/ ID3D10Buffer::Unmap()
对或ID3D10Device::UpdateSubresource()
方法。哪个更好用,取决于资源属性和更新频率(阅读Nvidia's "canonical" paper)。
用法非常简单。这是一个简单的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);
正如名称所述,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);
希望它有所帮助。
BTW,没有任何理由在2013年学习DirectX 10.您可以从DirectX 11开始,它的API几乎相同,但功能更多。1 此解释过于简化。我们永远无法确定给定资源所在的位置(GPU,系统内存,任何存储),因为驱动程序实现者需要决定何时以及何种类型的资源存储。
答案 1 :(得分:1)
提示:size是每个字节大小的顶点数量
D3D11_BOX srcBox{};
srcBox.left = srcBegin;
srcBox.right = srcBegin + size; <-here
srcBox.top = 0;
srcBox.bottom = 1;
srcBox.front = 0;
srcBox.back = 1;
Device->CopySubresourceRegion(pDst, 0, dstBegin, 0, 0, pSrc, 0, &srcBox);