reading GPU resource data by CPU

2019-08-01 10:58发布

问题:

i am learning directx11 these days. and i have been stuck in compute shader section.

so i made four resource and three corresponding view.

  1. immutable input buffer = {1,1,1,1,1} / SRV
  2. immutable input buffer = {2,2,2,2,2} / SRV
  3. output buffer / UAV
  4. staging buffer for reading / No View

and i succeeded to create all things, and dispatch cs function, and copy data from output buffer to staging buffer, and i read/check data.

// INPUT BUFFER1--------------------------------------------------
const int dataSize = 5;
    D3D11_BUFFER_DESC vb_dest;
    vb_dest.ByteWidth = sizeof(float) * dataSize;
    vb_dest.StructureByteStride = sizeof(float);
    vb_dest.BindFlags = D3D11_BIND_SHADER_RESOURCE;
    vb_dest.Usage = D3D11_USAGE_IMMUTABLE;
    vb_dest.CPUAccessFlags = 0;
    vb_dest.MiscFlags = 0;
    float v1_float[dataSize] = { 1,1,1,1,1 };
    D3D11_SUBRESOURCE_DATA v1_data;
    v1_data.pSysMem = static_cast<void*>(v1_float);
    device->CreateBuffer(
        &vb_dest,
        &v1_data,
        valueBuffer1.GetAddressOf());
    D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc;
    srv_desc.Format = DXGI_FORMAT_R32_FLOAT;
    srv_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
    srv_desc.Buffer.FirstElement = 0;
    srv_desc.Buffer.NumElements = dataSize;
    srv_desc.Buffer.ElementWidth = sizeof(float);
    device->CreateShaderResourceView(
        valueBuffer1.Get(),
        &srv_desc,
        inputSRV1.GetAddressOf());

// INPUT BUFFER2-----------------------------------------------------------
    float v2_float[dataSize] = { 2,2,2,2,2 };
    D3D11_SUBRESOURCE_DATA v2_data;
    v2_data.pSysMem = static_cast<void*>(v2_float);
    device->CreateBuffer(
        &vb_dest,
        &v2_data,
        valueBuffer2.GetAddressOf());
    device->CreateShaderResourceView(
        valueBuffer2.Get(),
        &srv_desc,
        inputSRV2.GetAddressOf());

// OUTPUT BUFFER-----------------------------------------------------------
    D3D11_BUFFER_DESC ov_desc;
    ov_desc.ByteWidth = sizeof(float) * dataSize;
    ov_desc.StructureByteStride = sizeof(float);
    ov_desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS;
    ov_desc.Usage = D3D11_USAGE_DEFAULT;
    ov_desc.CPUAccessFlags = 0;
    ov_desc.MiscFlags = 0;
    device->CreateBuffer(
        &ov_desc,
        nullptr,
        outputResource.GetAddressOf());

    D3D11_UNORDERED_ACCESS_VIEW_DESC outputUAV_desc;
    outputUAV_desc.Format = DXGI_FORMAT_R32_FLOAT;
    outputUAV_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
    outputUAV_desc.Buffer.FirstElement = 0;
    outputUAV_desc.Buffer.NumElements = dataSize;
    outputUAV_desc.Buffer.Flags = 0;
    device->CreateUnorderedAccessView(
        outputResource.Get(),
        &outputUAV_desc,
        outputUAV.GetAddressOf());

// BUFFER FOR COPY-----------------------------------------------------------
    D3D11_BUFFER_DESC rb_desc;
    rb_desc.ByteWidth = sizeof(float) * dataSize;
    rb_desc.StructureByteStride = sizeof(float);
    rb_desc.Usage = D3D11_USAGE_STAGING;
    rb_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
    rb_desc.BindFlags = 0;
    rb_desc.MiscFlags = 0;
    device->CreateBuffer(
        &rb_desc,
        nullptr,
        readResource.GetAddressOf());

// DISPATCH and COPY and GET DATA
    dContext->CSSetShaderResources(0, 1, inputSRV1.GetAddressOf());
    dContext->CSSetShaderResources(1, 1, inputSRV2.GetAddressOf());
    dContext->CSSetUnorderedAccessViews(0, 1, outputUAV.GetAddressOf(), nullptr);
    dContext->CSSetShader(cs.Get(), nullptr, 0);
    dContext->Dispatch(1, 1, 1);

    dContext->CopyResource(readResource.Get(), outputResource.Get());
    D3D11_MAPPED_SUBRESOURCE mappedResource2;
    ZeroMemory(&mappedResource2, sizeof(D3D11_MAPPED_SUBRESOURCE));
    R_CHECK(dContext->Map(readResource.Get(), 0, D3D11_MAP_READ, 0, &mappedResource2));

    float* data = static_cast<float*>(mappedResource2.pData);

    for (int i = 0; i < 5; ++i)
    {
        int a = data[i];
    }

and this is compute shader code


StructuredBuffer<float> inputA : register(t0);
StructuredBuffer<float> inputB : register(t1);

RWStructuredBuffer<float> output : register(u0);

[numthreads(5, 1, 1)]
void main(int3 id : SV_DispatchThreadID)
{
    output[id.x] = inputA[id.x] + inputB[id.x];
}

in CS, it's adding two input buffer data and store into output buffer. so expected answer would be {3,3,3,3,3}.

but the result is {3,0,0,0,0} only first idx has proper answer.

any advice would be amazing.

回答1:

 dContext->CopyResource(readResource.Get(), outputResource.Get());
    D3D11_MAPPED_SUBRESOURCE mappedResource2;
    ZeroMemory(&mappedResource2, sizeof(D3D11_MAPPED_SUBRESOURCE));
    R_CHECK(dContext->Map(readResource.Get(), 0, D3D11_MAP_READ, 0, &mappedResource2));

    float* data = static_cast<float*>(mappedResource2.pData);

    for (int i = 0; i < 5; ++i)
    {
        int a = data[i];
    }

this code should be like this.

CopyResource();
Map();
Declare and allocate 'data'
zeromemory(data);
memcopy(data, resource's pointer);
unMap();

for some reason, i have to use the memcopy instead of just reading resource directly with the pointer that i get from mapping.