[DX 11] cbuffer too small - what to do?

Started by
7 comments, last by MJP 13 years ago
Hi there,


I need to send a huge array from the CPU to the GPU. To be more precise I need the data only in the Domain Shader and it is updated every frame.

I used to do this with a constant buffer, but unfortunately it's size is limited to 4096 vectors, which my data now exceeds.

Can someone tell me an way to transmit such big amounts of data?


Cheers,
tr0x
Advertisement
You need to use a buffer resource, but bound to the stage with a shadier resource view. To hide the latency of the update coming from the cpu, you could use two buffers and alternate every frame. Or you could simply do the update of the buffer through the compute shader and keep eveything on the GPU.
Using a buffer or texture should be fine as long as you make it with D3D11_USAGE_DYNAMIC. You don't want to use a constant buffer for large amounts of data...it's not optimized for that scenario.
Thanks a lot for your answers!

So I want to transmit an array of float4s. What would be the best way to do so? I guess a 1D Texture would be appropriate, right? Could you give me a hint, how to fill the array with the data? Searching on msdn did not really enlighten me how to do that. I suppose it is a really easy thing to do, but as I am new to directX and hlsl things are a bit arcane to me yet.
Create a buffer resource with with ID3D11Device::CreateBuffer (using D3D11_USAGE_DYNAMIC), and create a shader resource view for it with format DXGI_FORMAT_R32G32B32A32_FLOAT. Then at runtime you can set the data in the buffer by calling ID3D11DeviceContext::Map, and copying in your data to the pointer you get from it. Then you bind the shader resource view to the domain shader stage with DSSetShaderResources, and in your HLSL shader declare a Buffer<float4> object. Then you can call Load on the buffer to access a value given an index.

You could also do the same with a 1D texture if you wanted, but a Buffer is probably the easiest way to go.
Thanks for your detailed explanation! Though I' am afraid I need your help once again.

I desperately tried to code what you told me, but I am simply not able to figure it out. :(

Here is my (awkward) code:


ID3D11ShaderResourceView* srv;
ID3D11Buffer* cps;

struct POINTS
{
float coords[512][4];
};

...

// create resource

D3D11_BUFFER_DESC Desc;
Desc.Usage = D3D11_USAGE_DYNAMIC;
Desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
Desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
Desc.MiscFlags = 0;

Desc.ByteWidth = sizeof( POINTS ) ;
V_RETURN( pd3dDevice->CreateBuffer( &Desc, NULL, &cps ) );
DXUT_SetDebugName( cps, "BUFFER" );


D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
srvDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;

pd3dDevice->CreateShaderResourceView( NULL, &srvDesc, &srv ); // what's the first parameter for?

// I can't see a connection between the buffer and the resource view here..

...

// per frame

D3D11_MAPPED_SUBRESOURCE MappedResource;
pd3dImmediateContext->Map( cps, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource );

POINTS* pData = (POINTS* )MappedResource.pData;

for( int i = 0; i < 512; i++)
for( int k = 0; k < 4; k++)
pData->coords[k] = 1.0f;

pd3dImmediateContext->Unmap( cps, 0 );


and in the shader:


Buffer<float4> testBuffer : register( c0 );

...

float4 test = testBuffer.Load(0);



I really hope you do take the time to look at it.
The first parameter should be your ID3D11Buffer pointer. The way shader resources work is you create a resource first (either a Buffer or Texture), and then you create a shader resource view for that resource that describes how a shader can sample from it. Each shader resource view is bound to a single resource, which is the resource you pass as the first parameter to CreateShaderResourceView. So in this case you want it bound to the Buffer, and you specify DXGI_FORMAT_R32G32B32A32_FLOAT to say "sample this buffer as an array of float4's".

Also make sure you fill out the rest of the D3D11_SHADER_RESOURCE_VIEW_DESC structure. Specifically, set ViewDimension to "D3D11_SRV_DIMENSION_BUFFER", and fill out the "Buffer" member as well. For that, set ElementOffset to 0 and ElementWidth to the number of float4 elements in the buffer (512 in your case).
:) It works! :)

I can't thank you enough!
You're welcome! Glad you got it working! :D

This topic is closed to new replies.

Advertisement