I figured out that my GPU (GTX690) can easily create new ID3D11Buffer's so fast that instead up updating an old buffer with new data using ID3D11DeviceContext::UpdateSubresource, I can just use ID3D11Device::CreateBuffer with initial data. Since I only touch ID3D11Device and not ID3D11DeviceContext, the whole operation can be done on another thread.
void DXDevice::SetMatrices(std::vector<DirectX::XMFLOAT4X4A> &Matrices)
{
auto pBuf = CreateStructuredBufferResource(Matrices.data(), Matrices.size() * sizeof(DirectX::XMFLOAT4X4A));
if (pBuf == nullptr)
throw std::exception("CreateStructuredBufferResource failed");
m_pImmediateContext->VSSetShaderResources(0, 1, &pBuf.p); // don't thread this
}
CComPtr<ID3D11ShaderResourceView> DXDevice::CreateStructuredBufferResource(const void* pDataSrc, UINT BufferSize)
{
CComPtr<ID3D11ShaderResourceView> pShaderResourceView{ nullptr };
CComPtr<ID3D11Buffer> pBuffer = CreateBufferResource(pDataSrc, BufferSize, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_DEFAULT, D3D11_RESOURCE_MISC_BUFFER_STRUCTURED);
if (pBuffer == nullptr)
return nullptr;
try
{
D3D11_SHADER_RESOURCE_VIEW_DESC rd;
ZeroMemory(&rd, sizeof(rd));
rd.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
rd.BufferEx.NumElements = BufferSize / sizeof(DirectX::XMFLOAT4X4A);
HR(m_pDevice->CreateShaderResourceView(pBuffer, &rd, &pShaderResourceView));
}
catch (std::exception &e)
{
WriteFile("error.log", e.what());
return nullptr;
}
return pShaderResourceView;
}
CComPtr<ID3D11Buffer> DXDevice::CreateBufferResource(const void* pDataSrc, UINT BufferSize, UINT BindFlags, D3D11_USAGE Usage, UINT MiscFlags)
{
CComPtr<ID3D11Buffer> pBuffer = nullptr;
try
{
if (BufferSize == 0)
throw std::exception("The requested buffer resource is of size 0");
D3D11_SUBRESOURCE_DATA sd;
ZeroMemory(&sd, sizeof(sd));
sd.pSysMem = pDataSrc;
D3D11_BUFFER_DESC bd;
ZeroMemory(&bd, sizeof(bd));
bd.Usage = Usage;
bd.ByteWidth = BufferSize;
bd.BindFlags = BindFlags;
bd.MiscFlags = MiscFlags;
if (MiscFlags == D3D11_RESOURCE_MISC_BUFFER_STRUCTURED)
bd.StructureByteStride = sizeof(DirectX::XMFLOAT4X4A);
HR(m_pDevice->CreateBuffer(&bd, pDataSrc ? &sd : nullptr, &pBuffer));
}
catch (std::exception &e)
{
WriteFile("error.log", e.what());
return nullptr;
}
return pBuffer;
}
StructuredBuffer<float4x4> Matrices : register(t0);