通过CPU读取GPU资源数据 [英] reading GPU resource data by CPU

查看:228
本文介绍了通过CPU读取GPU资源数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这些天,我正在学习DirectX11.而且我一直被困在计算着色器"部分.

所以我提出了四个资源和三个对应的视图.

  1. 不可变的输入缓冲区= {1,1,1,1,1}/SRV
  2. 不可变的输入缓冲区= {2,2,2,2,2}/SRV
  3. 输出缓冲区/无人机
  4. 用于读取/无视图的登台缓冲区

我成功地创建了所有东西,并调度了cs函数,并将数据从输出缓冲区复制到登台缓冲区,然后我读取/检查了数据.

// 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];
    }

这是计算着色器代码


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];
}

在CS中,它将两个输入缓冲区数据相加并存储到输出缓冲区中. 因此预期的答案将是{3,3,3,3,3}.

但是结果是{3,0,0,0,0}只有第一个idx有正确的答案.

任何建议都很棒.

解决方案

 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];
    }

此代码应该是这样的.

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

由于某些原因,我必须使用内存复制,而不是仅使用从映射中获取的指针直接读取资源.

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.

解决方案

 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.

这篇关于通过CPU读取GPU资源数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆