使用C ++ AMP读取缓冲区数据

时间:2014-10-19 07:08:15

标签: c++ directx c++-amp

我似乎无法让自己从AMP阵列中读取数据。

我想要做的是拿走我的缓冲区,将其复制到矢量中,然后使用矢量。我知道我应该设置CPU访问标志,但是我很难这样做。

首先,这就是我尝试访问缓冲区的方式。我先把它放在这里,以防万一我做了一些不应该做的事情。也许有一个内置的功能,我错过了为我做这个?

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);

基本上它应该将缓冲区中的所有数据写入向量

现在我知道我应该设置我的访问标记,但是我似乎无法做到这一点。我在初始化中写了以下函数:

m_Accelerator.set_default_cpu_access_type(concurrency::access_type::access_type_read_write);

但它会中断,并出现以下错误

"Invalid access_type specified. accelerator does not support zero copy."

我不确定这意味着什么,如果我试图将其设置为读写,是不是通过了测试?它也适用于我尝试的任何访问类型。

如何设置它以便我可以从缓冲区读取数据?

1 个答案:

答案 0 :(得分:0)

您可以创建DX缓冲区,然后使用make_array创建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;

请注意,设备和缓冲区必须满足一系列要求才能工作。 Direct3D设备必须实现功能级别为D3D_FEATURE_LEVEL_11_0或更高级别的ID3D11Device接口。可以从多个线程访问C ++ AMP accelerator_views,因此不应使用D3D11_CREATE_DEVICE_FLAG D3D11_CREATE_DEVICE_SINGLETHREADED设置创建设备。

Direct3D缓冲区必须实现ID3D11Buffer接口。它必须支持原始视图(D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS)并允许SHADER_RESOURCE和 UNORDERED_ACCESSbinding。缓冲区本身必须具有正确的大小,范围的大小 乘以缓冲区类型的大小。

您可以使用accelerator创建C ++ AMP create_accelerator_view,如下所示。

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);

这完全取自C++ AMP Book的第11章。