I am using D3D11 on D3D10 hardware, trying to get a very simple compute shader to run (my hardware supports cs_4_0).

What is the best way to pass data to the compute shader?

I've seen some samples use a constant buffer (cbuffer), but it seems very restrictive to me (in the hlsl cbuffer declaration I'd have to specify the amount of input (e.g. if a want to process an array of floats, I'd have to declare in my hlsl cbuffer an array of floats with a specific number of elements).

Other examples pass the input in the structured input the comp. shader will store the results in. Besides the fact that this might not suit my particular algorithm (maybe a thread needs access to more that just one element) I can't declare my structured input as dynamic, so to update it from the cpu (i.e. to add new values for the GPU to process) I'd have to use UpdateSubresource, which is not as efficient as Map, Unmap.

So, there must be a better way to send input to the Compute Shader. Any suggestions?

• Where you put your data and how you structure and update it totally depends on what you want to do with it. Do your algorithms use mostly random or sequential access? Does the data need to be read-only, write-only, or both? These are all questions that will affect your choices. – jmegaffin Feb 25 '14 at 20:14
• I just want to send input as fast as possible to the GPU. It will only be read by the GPU (not writen-to), and the GPU will not know beforehand how many elements are in the input. – Ziuck Feb 25 '14 at 20:19

I would use:

• One structured buffer (read-only) for the input
• Another structured buffer (read-write) for the output
• A constant buffer to store a few global parameters, if necessary, such as the size of the arrays.

For example:

struct Input { /* blah blah */ };
StructuredBuffer<Input> inputArray : register(t0);      // Shader resource binding

struct Output { /* blah blah */ };
RWStructuredBuffer<Output> outputArray : register(u0);  // UAV binding

cbuffer globals : register(b0)
{
float someParameter;
float anotherParameter;
uint numInputs;
};


Constant buffers are not designed for large amounts of data (more than a few kilobytes at a time). However, they are designed to be efficient to access, especially when all the threads in the dispatch are going to be looking at the same constants.

Structured buffers are better suited for larger amounts of data, where individual threads are going to be reading/writing individual records. (Although keeping data in SOA instead of AOS layout benefits the GPU memory system just as it does in CPU SIMD code. I would consider using SOA if your structs are going to be bigger than 16 bytes.)

You can have multiple structured buffers. Some can be read-only, and some can be read-write. There's no requirement that you use the same buffer for both input and output.

Also note that another possibility is typed buffers, like Buffer<float4>, in cases where the buffer format matches one of the DXGI formats.

Last, I don't know why you said you "can't declare my structured input as dynamic". There should be no problem with creating a structured buffer with dynamic usage, allowing you to use Map/Unmap. This is certainly allowed by the API. The only restriction is that you can't use the NO_OVERWRITE map flag (prior to D3D11.1); you have to use DISCARD instead.

• Hi! I couldn't set the Dynamic flag as my structured buffer also had the UnorderedAccessView flag set as well. Following your suggestions I have StructuredBuffer and a srView for input, and a RWStructuredBuffer and a uaView for the output. It works! p.s. So, to use a typed buffer instead, I don't add the Buffer_Structured flag to the bufferDesc, and for the srViewDecs, the format is set to whatever the buffer type is (instead of unknown). Is that correct? – Ziuck Feb 25 '14 at 23:57
• @Ziuck Yes, I think that's right. – Nathan Reed Feb 26 '14 at 4:12