Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm trying to learn graphics programming and DirectX11.

I'm trying to learn how to minimize CPU-GPU transfer and graphics programming in general.
I have a question that I have been unable to answer myself from online resources:

Which of the D3D methods actually sends the data to the GPU(and, equivalently, for a static mesh does ALL the vertex data get passed to the GPU every frame, or only once)?

Code follows:
(simplified for stackexchange)

In my "mesh" class, I have a vertex buffer:

ID3D11Buffer *m_pVBuffer;

In my mesh's constructor, I set some vertices to the vertex buffer:

D3D11_MAPPED_SUBRESOURCE ms;
devcon->Map(m_pVBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &ms);
memcpy(ms.pData, &vertices[0], sizeof(VERTEX) * vertices.size());
devcon->Unmap(m_pVBuffer, NULL);

Then in my mesh's "render" method, I do this:

UINT stride = sizeof(VERTEX);
UINT offset = 0;
devcon->IASetVertexBuffers(0, 1, &m_pVBuffer, &stride, &offset);
devcon->IASetIndexBuffer(m_pIBuffer, DXGI_FORMAT_R32_UINT, 0);
devcon->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
devcon->DrawIndexed(m_num_indices, 0, 0);

To repeat: Is the data uploaded to the GPU when I Map, memcpy and Unmap the vertex buffer, or is it uploaded every frame, when I call IASetVertexBuffers?

share|improve this question
add comment

3 Answers

up vote 6 down vote accepted

This is a tricky question because you don't have complete control over whether a vertex buffer is stored in VRAM or main RAM. The driver makes that decision for you based on the usage and CPU access flags specified when you create the vertex buffer.

Generally speaking, buffers with default and immutable usage will be stored in VRAM; those with staging usage will be stored in main RAM; and those with dynamic usage could be in either place. However, if insufficient VRAM is available the driver will store resources in main RAM as a fallback.

If a buffer ends up in VRAM, data goes across the system bus (that connects the CPU and GPU) whenever the CPU updates the buffer (that is, when you do a Map/Unmap pair). If it's in main RAM, the GPU will read the data across the system bus every time you use that buffer for rendering.

So, typically, for static meshes you would use immutable usage and the buffer would be stored in VRAM, so there is no additional system bus transfer after the initial setup. For a dynamic vertex buffer (for particles or similar) you'd use dynamic usage, and the data would go across the bus once each frame - if it's in VRAM, the bus will be used for the CPU to write to it, and if it's in main RAM, the bus will be used for the GPU to read it.

share|improve this answer
    
The tests I ran confirm this answer. When I render a lot of objects, there's an initial slowdown for the first couple of seconds but then the framerate goes up. Given that I do the same thing every frame, this must be because at least some part of the buffers is "cached" in VRAM. So the answer is "It will be uploaded only once. Probably. You shouldn't count on it though.". –  x10 Jan 10 '12 at 15:30
add comment

The answer will be dependent on what any particular generation of highly optimized hardware driver feels like doing, which is to say that there is no general answer for you.

Add to that complication the fact that drivers are rendering 1-N frames behind of what you're currently telling them to render because 3D cards are both highly serialized and parallel and cached and work asynchronously to get things done.

If you're just learning then the important information to know is the sequence points to preparing a render: describe the data, copy in the data, tell the driver what data to use, then fire off the render. And not what happens when, that is a very deep rabbit hole indeed.

share|improve this answer
add comment

My understanding, mostly based on reading this is that the driver generally won't send any resources across to video memory, until the resource is used in a draw call.

That would mean the constructor probably won't touch the GPU hardware at all, and the render method will. However even the DrawIndexed() call probably won't make it to the hardware immediately because it's more CPU efficient to buffer up large lists of GPU commands.

The driver can also unload data from GPU memory when it runs out (assuming it has a copy of it in main RAM). In extreme cases this can happen more than once per frame.

Of course all of this is hidden from the programmer by the driver, so you can't rely on it being like that - drivers change all the time.

share|improve this answer
    
It's highly possible that it won't even go on a draw call - the draw call just goes to a driver-managed command buffer, and that gets flushed in the drivers own sweet time, which may be any arbitrary amount of time afterwards. –  Jimmy Shelter Jun 26 '12 at 21:32
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.