How to create large upload buffers?

Started by
6 comments, last by lubbe75 5 years, 9 months ago

I want to stress my application by rendering lots of polygons. I use DX12 (SharpDX) and I upload all vertices to GPU memory via an upload buffer. In normal cases everything works fine, but when I try to create a large upload buffer (CreateCommittedResource) I get a non-informative exception from SharpDX, and the device is being removed. GetDeviceRemovedReason (DeviceRemovedReason in SharpDX) returns 0x887A0020: DXGI_ERROR_DRIVER_INTERNAL_ERROR. 

I'm guessing it's all because it can't find a consecutive chunk of memory big enough to create the buffer (I have 6GB on the card and I'm currently trying to allocate a buffer smaller than 1GB).

So how do I deal with this? I guess I could create several smaller buffers instead, but I can't just put the CreateCommittedResource call in a try-catch section. The exception is serious enough to remove my device, so any further attempts will fail after the first try.

Can I somehow know beforehand what size is OK to allocate?

Advertisement

Sounds like the problem is coming from the driver. What driver(s) have you tried this on?

Not sure if this helps, but I can successfully allocate a 2GB upload buffer on my Nvidia GTX 1070 and AMD RX 460. At 4GB I get a device removed on my AMD card with the same error code:

(Device removal has been triggered for the following reason (DXGI_ERROR_DRIVER_INTERNAL_ERROR: There is strong evidence that the driver has performed an undefined operation; but it may be because the application performed an illegal or undefined operation to begin with.). [ EXECUTION WARNING #233: DEVICE_REMOVAL_PROCESS_POSSIBLY_AT_FAULT]

On my 1070 the Nvidia user-mode driver just flat-out crashes with an integer divide-by-zero exception. So yeah, it seems like there's some driver issues here.

Ok, that's Interesting. I have a GeForce GTX 1060 6GB, driver version 390.65. Now that I upgraded to driver 398.11 I still get the same results.

So, I'm working my way around the problem by creating several small upload buffers, but I don't know at what size I should break and create another upload buffer. Too small buffers are not efficient, and too big will trigger the error. For now I just set the limit to around 100 Mb, and it works.

It may not help but googling in OpenGL reveals you may be able to do this:


GLint size;
glGetIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &size);

and the docs suggest:

GL_MAX_SHADER_STORAGE_BLOCK_SIZE (64-bit integer, minimum is 2^24 (16,777,216)) The maximum size in basic machine units of a shader storage block.

I'm not suggesting you fire up OpenGL just to get the max size (it may be different anyway in DX) but I wouldn't be surprised if the same minimum size applied (16 megs).

6 hours ago, lubbe75 said:

So, I'm working my way around the problem by creating several small upload buffers

If you're actually using them for uploading data, you don't need them to be very large at all, and you only need one. You use the CPU to copy some data into half your buffer, then tell the GPU's Copy Queue to move it from there into a real GPU-resident buffer. Then you repeat in the second half of your buffer. Then you check if the first copy queue command has finished, and if so, send the 3rd chunk via the first half of the buffer again, etc...

A few hundred meg should be plenty big enough to stream gigabytes of data through to the GPU very quickly in this way.

That's what I do. It's just that I take a number (for maximum buffer size) out of thin air. It feels wrong, but it works.

This topic is closed to new replies.

Advertisement