问题
I can't seem to find a way to let myself read the data from my AMP array.
What I want to be able to do, is take my buffer, copy it into a vector and then use the vector. I'm aware that I should set the CPU access flags, but I'm having trouble doing so.
Firstly, this is how I'm trying to access the buffer. I'm putting this here first just in case I have done something how it shouldn't be done. Perhaps there is a function built in that I've missed that does this for me?
std::vector<Pticle> vecParticles;
ID3D11Buffer* pBuffer = reinterpret_cast<ID3D11Buffer *>(concurrency::direct3d::get_buffer(m_arrParticles));
D3D11_MAPPED_SUBRESOURCE MappedResource;
m_pDeviceContext->Map(pBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource);
{
auto pData = (Pticle*)MappedResource.pData;
for (unsigned i = 0; i < m_uiNumParticles; ++i)
{
vecParticles.push_back(pData[i]);
}
}
m_pDeviceContext->Unmap(pBuffer, 0);
Basically it should write all the data from the buffer into the vector
Now I know I should set my access flags, however I can't seem to do it. I write in the following function in my initialise:
m_Accelerator.set_default_cpu_access_type(concurrency::access_type::access_type_read_write);
however it breaks, with the following error
"Invalid access_type specified. accelerator does not support zero copy."
I'm not sure what this means, if I'm attempting to set it up to read and write, didn't it pass the test? It also does it on any access type I try.
How can I set it up so that I can read the data from the buffer?
回答1:
You can create a DX buffer and then use make_array
to create a C++AMP array
.
HRESULT hr = S_OK;
UINT bufferSize = 1024;
D3D11_BUFFER_DESC bufferDesc =
{
bufferSize * sizeof(float),
D3D11_USAGE_DEFAULT,
D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_SHADER_RESOURCE |
D3D11_BIND_UNORDERED_ACCESS,
0 /* no CPU access */,
D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS /* misc flags */,
sizeof(float)
};
D3D11_SUBRESOURCE_DATA resourceData;
ZeroMemory(&resourceData, sizeof(D3D11_SUBRESOURCE_DATA));
std::vector<float> vertices(bufferSize, 1.0f);
resourceData.pSysMem = &vertices[0];
CComPtr<ID3D11Buffer> buffer;
hr = device->CreateBuffer(&bufferDesc, &resourceData, &buffer);
assert(SUCCEEDED(hr));
array<float, 1> arr = make_array<float, 1>(extent<1>(bufferSize), dxView, buffer);
std::wcout << "Created array<float,1> on "
<< arr.accelerator_view.accelerator.description << std::endl;
Note that the device and buffer must meet a set of requirements for this to work. The Direct3D device must implement the ID3D11Deviceinterface with feature level D3D_FEATURE_LEVEL_11_0 or above. C++ AMP accelerator_views can be accessed from multiple threads, so the device should not be created with the D3D11_CREATE_DEVICE_FLAG D3D11_CREATE_DEVICE_SINGLETHREADED set.
The Direct3D buffer must implement the ID3D11Bufferinterface. It must support raw views (D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS) and allow SHADER_RESOURCE and UNORDERED_ACCESSbinding. The buffer itself must be of the correct size, the size of the extent multiplied by the size of the buffer type.
You can create a C++ AMP accelerator
using create_accelerator_view
as shown here.
HRESULT hr = S_OK;
UINT createDeviceFlags = 0;
#ifdef _DEBUG
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
std::array<D3D_FEATURE_LEVEL, 1> featureLevels = { D3D_FEATURE_LEVEL_11_0 };
CComPtr<ID3D11Device> device;
D3D_FEATURE_LEVEL featureLevel;
CComPtr<ID3D11DeviceContext> immediateContext;
hr = D3D11CreateDevice(nullptr /* default adapter */,
D3D_DRIVER_TYPE_HARDWARE,
nullptr /* No software rasterizer */,
createDeviceFlags,
featureLevels.data(),
UINT(featureLevels.size()),
D3D11_SDK_VERSION,
&device,
&featureLevel,
&immediateContext);
assert(SUCCEEDED(hr));
accelerator_view dxView = create_accelerator_view(device);
This is all taken from Chapter 11 of the C++ AMP Book.
来源:https://stackoverflow.com/questions/26448227/reading-buffer-data-using-c-amp