Hi,
I have implemented a D3D11 application that uses ID3DX11Scan (d3dcsx.lib) to do a parallel prefix sum of a UAV buffer into another UAV buffer. This works very well when using an integrated Intel GPU. However, when I try using my GTX 680 with driver version 347.52 it does not seem to work any more. I am using DXGI_FORMAT_R32_SINT since unsigned ints did not work for me during implementation (using an integrated Intel GPU).
According to the following forum link, only signed ints are supported (which I think is a bit weird since it is not mentioned in the Microsoft docs)
http://xboxforums.create.msdn.com/forums/p/79535/484267.aspx
ID3DX11Scan::Scan (d3dcsx.h) - Win32 apps | Microsoft Docs
Anyways, my code fails (silently! runs fine without bad HRESULT) and looks something like this for creating the scan:
INT32 dx = (INT32)ceil(g_streamDesc.RecommendedDim.X / (DOUBLE)BrickSize);
INT32 dy = (INT32)ceil(g_streamDesc.RecommendedDim.Y / (DOUBLE)BrickSize);
INT32 dz = (INT32)ceil(g_streamDesc.RecommendedDim.Z / (DOUBLE)BrickSize);
INT32 count = (dx * dy * dz);
ID3DX11Scan* scan = nullptr;
hr = D3DX11CreateScan(sdAdapter->ImmediateContext.Get(), count, 1, &scan);
S3D_VERIFY(SUCCEEDED(hr));
hr = scan->SetScanDirection(D3DX11_SCAN_DIRECTION_FORWARD);
S3D_VERIFY(SUCCEEDED(hr));
sdAdapter->Resources.Scans.Insert("PrefixSumScan", scan);
Then the usage is as follows:
INT32 dx = (INT32)ceil(g_streamDesc.RecommendedDim.X / (DOUBLE)BrickSize);
INT32 dy = (INT32)ceil(g_streamDesc.RecommendedDim.Y / (DOUBLE)BrickSize);
INT32 dz = (INT32)ceil(g_streamDesc.RecommendedDim.Z / (DOUBLE)BrickSize);
INT32 count = (dx * dy * dz);
HRESULT hr{};
ID3DX11Scan* scan = sdAdapter->Resources.Scans["PrefixSumScan"].Get();
S3D_VERIFY(scan != nullptr);
// Note: Scan only seems to work with SINT (not UINT) data..
hr = scan->Scan(D3DX11_SCAN_DATA_TYPE_INT, D3DX11_SCAN_OPCODE_ADD, count,
sdAdapter->Resources.UnorderedAccessViews["LookupSphereCountBufferUAView"].Get(),
sdAdapter->Resources.UnorderedAccessViews["LookupSpherePrefixSumBufferUAView"].Get());
S3D_VERIFY(SUCCEEDED(hr));
Is the ID3DX11Scan utility properly supported and supposed to work? Have I implemented the feature properly or is there something I am doing wrong? This code behaves as expected on my Intel integrated GPU (though they dont support UINT format).
My buffers are created with the following code:
// LookupSphereCountBuffer
{
INT32 dx = (INT32)ceil(g_streamDesc.RecommendedDim.X / (DOUBLE)BrickSize);
INT32 dy = (INT32)ceil(g_streamDesc.RecommendedDim.Y / (DOUBLE)BrickSize);
INT32 dz = (INT32)ceil(g_streamDesc.RecommendedDim.Z / (DOUBLE)BrickSize);
D3D11_BUFFER_DESC desc{};
desc.ByteWidth = (sizeof(INT32) * (dx * dy * dz));
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS;
desc.Usage = D3D11_USAGE_DEFAULT; // A resource that requires read and write access by the GPU.
desc.CPUAccessFlags = 0;
// Create texture.
ComPtr<ID3D11Buffer> buffer{};
hr = sdAdapter->Device->CreateBuffer(&desc, nullptr, &buffer);
if (!S3D_VERIFY_MSG(SUCCEEDED(hr), "CreateBuffer - failed!"))
{
return hr;
}
sdAdapter->Resources.Buffers.Insert(SetDebugObjectName(buffer.Get(), "LookupSphereCountBuffer"), buffer);
D3D11_SHADER_RESOURCE_VIEW_DESC srDesc{};
srDesc.Buffer.NumElements = (dx * dy * dz);
srDesc.Buffer.ElementOffset = 0;
srDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
srDesc.Format = DXGI_FORMAT_R32_SINT;
// Create a resource view of the texture.
ComPtr<ID3D11ShaderResourceView> srView{};
hr = sdAdapter->Device->CreateShaderResourceView(buffer.Get(), &srDesc, &srView);
if (!S3D_VERIFY_MSG(SUCCEEDED(hr), "CreateShaderResourceView - failed!"))
{
return hr;
}
sdAdapter->Resources.ShaderResourceViews.Insert(SetDebugObjectName(srView.Get(), "LookupSphereCountBufferSRView"), srView);
D3D11_UNORDERED_ACCESS_VIEW_DESC uaDesc{};
uaDesc.Buffer.NumElements = (dx * dy * dz);
uaDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
uaDesc.Format = DXGI_FORMAT_R32_SINT;
// Create a uav from the texture.
ComPtr<ID3D11UnorderedAccessView> uaView{};
hr = sdAdapter->Device->CreateUnorderedAccessView(buffer.Get(), &uaDesc, &uaView);
if (!S3D_VERIFY_MSG(SUCCEEDED(hr), "CreateUnorderedAccessView - failed!"))
{
return hr;
}
sdAdapter->Resources.UnorderedAccessViews.Insert(SetDebugObjectName(uaView.Get(), "LookupSphereCountBufferUAView"), uaView);
}
// LookupSpherePrefixSumBuffer
{
INT32 dx = (INT32)ceil(g_streamDesc.RecommendedDim.X / (DOUBLE)BrickSize);
INT32 dy = (INT32)ceil(g_streamDesc.RecommendedDim.Y / (DOUBLE)BrickSize);
INT32 dz = (INT32)ceil(g_streamDesc.RecommendedDim.Z / (DOUBLE)BrickSize);
D3D11_BUFFER_DESC desc{};
desc.ByteWidth = (sizeof(INT32) * (dx * dy * dz));
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS;
desc.Usage = D3D11_USAGE_DEFAULT; // A resource that requires read and write access by the GPU.
desc.CPUAccessFlags = 0;
// Create texture.
ComPtr<ID3D11Buffer> buffer{};
hr = sdAdapter->Device->CreateBuffer(&desc, nullptr, &buffer);
if (!S3D_VERIFY_MSG(SUCCEEDED(hr), "CreateBuffer - failed!"))
{
return hr;
}
sdAdapter->Resources.Buffers.Insert(SetDebugObjectName(buffer.Get(), "LookupSpherePrefixSumBuffer"), buffer);
D3D11_SHADER_RESOURCE_VIEW_DESC srDesc{};
srDesc.Buffer.NumElements = (dx * dy * dz);
srDesc.Buffer.ElementOffset = 0;
srDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
srDesc.Format = DXGI_FORMAT_R32_SINT;
// Create a resource view of the texture.
ComPtr<ID3D11ShaderResourceView> srView{};
hr = sdAdapter->Device->CreateShaderResourceView(buffer.Get(), &srDesc, &srView);
if (!S3D_VERIFY_MSG(SUCCEEDED(hr), "CreateShaderResourceView - failed!"))
{
return hr;
}
sdAdapter->Resources.ShaderResourceViews.Insert(SetDebugObjectName(srView.Get(), "LookupSpherePrefixSumBufferSRView"), srView);
D3D11_UNORDERED_ACCESS_VIEW_DESC uaDesc{};
uaDesc.Buffer.NumElements = (dx * dy * dz);
uaDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
uaDesc.Format = DXGI_FORMAT_R32_SINT;
// Create a uav from the texture.
ComPtr<ID3D11UnorderedAccessView> uaView{};
hr = sdAdapter->Device->CreateUnorderedAccessView(buffer.Get(), &uaDesc, &uaView);
if (!S3D_VERIFY_MSG(SUCCEEDED(hr), "CreateUnorderedAccessView - failed!"))
{
return hr;
}
sdAdapter->Resources.UnorderedAccessViews.Insert(SetDebugObjectName(uaView.Get(), "LookupSpherePrefixSumBufferUAView"), uaView);
}
Let me know if you need to know more,
Jørn