1

DirectX11 計算シェーダーで texture2d からデータを読み込もうとしていますが、テクスチャ オブジェクトが同じ浮動小数点数で満たされていても、texture2D オブジェクトの「Load」関数は 0 を返し続けます。

これは、DXGI_FORMAT_R32G32B32A32_FLOAT を使用した 160 * 120 の texture2d です。次のコードは、このリソースの作成方法です。

HRESULT TestResources(ID3D11Device* pd3dDevice, ID3D11DeviceContext* pImmediateContext) {
    float *test = new float[4 * 80 * 60 * 4]; // 80 * 60, 4 channels, 1 big texture contains 4 80 * 60 subimage
    for (int i = 0; i < 4 * 80 * 60 * 4; i++) test[i] = 0.7f;

    HRESULT hr = S_OK;
    D3D11_TEXTURE2D_DESC RTtextureDesc;
    ZeroMemory(&RTtextureDesc, sizeof(D3D11_TEXTURE2D_DESC));
    RTtextureDesc.Width = 160;
    RTtextureDesc.Height = 120;
    RTtextureDesc.MipLevels = 1;
    RTtextureDesc.ArraySize = 1;
    RTtextureDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;

    RTtextureDesc.SampleDesc.Count = 1;
    RTtextureDesc.SampleDesc.Quality = 0;
    RTtextureDesc.Usage = D3D11_USAGE_DYNAMIC;
    RTtextureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
    RTtextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    RTtextureDesc.MiscFlags = 0;

    D3D11_SUBRESOURCE_DATA InitData;
    InitData.pSysMem = test;
    InitData.SysMemPitch = sizeof(float) * 4;
    V_RETURN(pd3dDevice->CreateTexture2D(&RTtextureDesc, &InitData, &m_pInputTex2Ds));
    //V_RETURN(pd3dDevice->CreateTexture2D(&RTtextureDesc, NULL, &m_pInputTex2Ds));

    D3D11_SHADER_RESOURCE_VIEW_DESC SRViewDesc;
    ZeroMemory(&SRViewDesc, sizeof(SRViewDesc));
    SRViewDesc.Format = RTtextureDesc.Format;
    SRViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
    SRViewDesc.Texture2D.MostDetailedMip = 0;
    SRViewDesc.Texture2D.MipLevels = 1;
    V_RETURN(pd3dDevice->CreateShaderResourceView(m_pInputTex2Ds, &SRViewDesc, &m_pInputTexSRV));

    delete[] test;
    return hr;
}

そして、次のように X = Y = 2 および Z = 1 でディスパッチを実行しようとします。

void ComputeShaderReduction::ExecuteComputeShader(ID3D11DeviceContext* pd3dImmediateContext, UINT uInputNum, ID3D11UnorderedAccessView** ppUAVInputs, UINT X, UINT Y, UINT Z) {
    pd3dImmediateContext->CSSetShader(m_pComputeShader, nullptr, 0);

    pd3dImmediateContext->CSSetShaderResources(0, 1, &m_pInputTexSRV); // test code

    pd3dImmediateContext->CSSetUnorderedAccessViews(0, uInputNum, ppUAVInputs, nullptr);
    //pd3dImmediateContext->CSSetUnorderedAccessViews(0, 1, &m_pGPUOutUAVs, nullptr);

    pd3dImmediateContext->UpdateSubresource(m_pConstBuf, 0, nullptr, &m_ConstBuf, 0, 0);
    pd3dImmediateContext->CSSetConstantBuffers(0, 1, &m_pConstBuf);
    pd3dImmediateContext->Dispatch(X, Y, Z);

    pd3dImmediateContext->CSSetShader(nullptr, nullptr, 0);

    ID3D11UnorderedAccessView* ppUAViewnullptr[1] = { nullptr };
    pd3dImmediateContext->CSSetUnorderedAccessViews(0, 1, ppUAViewnullptr, nullptr);

    ID3D11ShaderResourceView* ppSRVnullptr[1] = { nullptr };
    pd3dImmediateContext->CSSetShaderResources(0, 1, ppSRVnullptr);

    ID3D11Buffer* ppCBnullptr[1] = { nullptr };
    pd3dImmediateContext->CSSetConstantBuffers(0, 1, ppCBnullptr);
}

そして、非常に単純な CS シェーダーを作成して、texture2d 内のデータを取得し、それからデータを取得しようとしました。したがって、計算シェーダーは次のようになります。

#define subimg_dim_x 80
#define subimg_dim_y 60

Texture2D<float4> BufferIn : register(t0);
StructuredBuffer<float> Test: register(t1);
RWStructuredBuffer<float> BufferOut : register(u0);

groupshared float sdata[subimg_dim_x];

[numthreads(subimg_dim_x, 1, 1)]
void CSMain(uint3 DTid : SV_DispatchThreadID,
            uint3 threadIdx : SV_GroupThreadID,
            uint3 groupIdx  : SV_GroupID) {

    sdata[threadIdx.x] = 0.0;
    GroupMemoryBarrierWithGroupSync();

    if (threadIdx.x == 0) {
        float4 num = BufferIn.Load(uint3(groupIdx.x, groupIdx.y, 1));
        //BufferOut[groupIdx.y * 2 + groupIdx.x] = 2.0; //This one gives me 2.0 as output in the console
        BufferOut[groupIdx.y * 2 + groupIdx.x] = num.x; //This one keeps giving me 0.0 and in the texture, r = g = b = a = 0.7 or x = y = z = w = 0.7, so it suppose to print 0.7 in the console.
    }
    GroupMemoryBarrierWithGroupSync();
}

CPU 側で CS シェーダーの結果を出力する方法は正しいと思います。

void ComputeShaderReduction::CopyToCPUBuffer(ID3D11Device* pdevice, ID3D11DeviceContext* pd3dImmediateContext, ID3D11Buffer* pGPUOutBufs) {
    D3D11_BUFFER_DESC desc;
    ZeroMemory(&desc, sizeof(desc));
    pGPUOutBufs->GetDesc(&desc);
    desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
    desc.Usage = D3D11_USAGE_STAGING;
    desc.BindFlags = 0;
    desc.MiscFlags = 0;
    if (!m_pCPUOutBufs && SUCCEEDED(pdevice->CreateBuffer(&desc, nullptr, &m_pCPUOutBufs))) {
        pd3dImmediateContext->CopyResource(m_pCPUOutBufs, pGPUOutBufs);
    }
    else pd3dImmediateContext->CopyResource(m_pCPUOutBufs, pGPUOutBufs);

    D3D11_MAPPED_SUBRESOURCE MappedResource;
    float *p;
    pd3dImmediateContext->Map(m_pCPUOutBufs, 0, D3D11_MAP_READ, 0, &MappedResource);
    p = (float*)MappedResource.pData;
    for (int i = 0; i < 4; i++) printf("%d %f\n", i, p[i]);
    pd3dImmediateContext->Unmap(m_pCPUOutBufs, 0);
    printf("\n");
}

UAV にバインドするバッファーには 4 つの要素しかありません。したがって、texture2d のすべての浮動小数点数が 0.7 の場合、0.0 ではなく 4 つの 0.7 が CopyToCPUBuffer 関数で出力されるはずです。

私のコードで何が間違っているのか知っている人はいますか、または計算シェーダーで DirectX 11 texture2d のデータを正しく読み取る方法を示す完全な例またはチュートリアルを誰かが提供してくれますか?

前もって感謝します。

4

1 に答える 1