I have a snow particle system and I use simplex noise for creating turbulence effect.
At first, I made calculations on the CPU, and the simplex noise calls obviously were the bottleneck.
The MAX_NUM_PARTICLES
limit was 50k (to hold the 60 fps). There was a fatal drop for 75-100k.
That's why I moved the calculation to compute shader like here.
Snow particle system is working, however, I got a weird result: the fps limit left the same, but it does not fall so critically -- I can render 100-200k with 45 fps.
At first, I played with Dispatch
params, but the fps was the same for 512, 1, 1
and 1, 1, 1
calls.
Second, I convinced that simplex noise calculations were not a problem just passing input coordinates into the output buffer.
Then I commented out different parts of the code and realized that ID3D11DeviceContext:::CopyResource
is the bottleneck. I use RWStructuredBuffer
buffer to gain compute shader results and, as I know, it requires additional buffer with D3D11_USAGE_STAGING
usage and D3D11_CPU_ACCESS_READ
flag. So think I can't refuse to use it.
Please share your ideas What can I do about it?
Code part:
// Create a system memory version of the buffer to read the results back from.
outputDesc.Usage = D3D11_USAGE_STAGING;
outputDesc.BindFlags = 0;
outputDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
result = (device->CreateBuffer(&outputDesc, 0, &mRWOutputBuffer));
if (FAILED(result))
return false;
D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
uavDesc.Buffer.FirstElement = 0;
uavDesc.Buffer.Flags = 0;
uavDesc.Buffer.NumElements = m_pParticleSystem->GetInstaceCount();
uavDesc.Format = DXGI_FORMAT_UNKNOWN;
uavDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
result = device->CreateUnorderedAccessView(mRWBuffer, &uavDesc, &mRWUAV);
if (FAILED(result))
return false;
m_pParticleSystem->FillConstantDataBuffer(deviceContext, mInputBuffer);
// Enable Compute Shader
deviceContext->CSSetShader(mComputeShader, nullptr, 0);
deviceContext->CSSetShaderResources(0, 1, &mInputView);
deviceContext->CSSetUnorderedAccessViews(0, 1, &mRWUAV, 0);
// Dispatch
deviceContext->Dispatch(512, 1, 1);
// Unbind the input textures from the CS for good housekeeping
ID3D11ShaderResourceView* nullSRV[] = { NULL };
deviceContext->CSSetShaderResources(0, 1, nullSRV);
// Unbind output from compute shader ( we are going to use this output as an input in the next pass,
// and a resource cannot be both an output and input at the same time
ID3D11UnorderedAccessView* nullUAV[] = { NULL };
deviceContext->CSSetUnorderedAccessViews(0, 1, nullUAV, 0);
// Disable Compute Shader
deviceContext->CSSetShader(nullptr, nullptr, 0);
// Copy result **(FPS DROP HERE)**
deviceContext->CopyResource(mRWOutputBuffer, mRWBuffer);
Thank you for your answer in advance.