0
votes

I cannot initialize a ByteAddressBuffer from my C++ application: every API call succeed but in the shader, the data is always 0xFF.

To create and initialize the ByteAddressBuffer, I use the function below. pInitData point to a buffer containing a RGB image (uElementSize is 3, uCount is number of pixels).

// Create a RAW buffer to store the images bits for shader access
HRESULT BIPApplication::CreateRawImageBuffer(
    UINT  uElementSize,
    UINT  uCount,
    void* pInitData)
{
    D3D11_BUFFER_DESC        desc;
    D3D11_SUBRESOURCE_DATA   InitData;
    HRESULT                  hr;

    SAFE_RELEASE(FRawImageBuffer);

    ZeroMemory(&desc, sizeof(desc));
    desc.BindFlags           = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
    desc.Usage               = D3D11_USAGE_DEFAULT;
    desc.CPUAccessFlags      = 0; 
    desc.ByteWidth           = (((uElementSize * uCount) + 15) / 16) * 16;
    desc.MiscFlags           = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
    desc.StructureByteStride = 0; 

    if (pInitData) {
        InitData.pSysMem = pInitData;
        hr = g_pd3dDevice->CreateBuffer(&desc, &InitData, &FRawImageBuffer);
    }
    else
        hr = g_pd3dDevice->CreateBuffer(&desc, NULL, &FRawImageBuffer);

#if defined(_DEBUG) || defined(PROFILE)
    if (SUCCEEDED(hr) && (FRawImageBuffer != NULL))
        FRawImageBuffer->SetPrivateData(WKPDID_D3DDebugObjectName,
                                        sizeof("RawImageBuffer"),
                                        "RawImageBuffer");
#endif
    return hr;
}

Then I create a shader resource view to be used by the compute shader:

// Create a shader resource view on the RAW image buffer
HRESULT BIPApplication::CreateRawImageShaderResourceView()
{
    D3D11_BUFFER_DESC               descBuf;
    D3D11_SHADER_RESOURCE_VIEW_DESC desc;

    ZeroMemory(&descBuf, sizeof(descBuf));
    FRawImageBuffer->GetDesc(&descBuf);

    ZeroMemory(&desc, sizeof(desc));
    desc.ViewDimension         = D3D11_SRV_DIMENSION_BUFFEREX;
    desc.BufferEx.FirstElement = 0;
    desc.Format                = DXGI_FORMAT_R32_TYPELESS;
    desc.BufferEx.Flags        = D3D11_BUFFEREX_SRV_FLAG_RAW;
    desc.BufferEx.NumElements  = descBuf.ByteWidth / 4;
    return g_pd3dDevice->CreateShaderResourceView(FRawImageBuffer, &desc, &FRawImageSRV);
}

Then in the Render() function, I pass the SRV to the shader:

// For ComputeShader RAW image data
aRViews[0] = FRawImageSRV;
g_pImmediateContext->CSSetShaderResources(0, 1, aRViews);

In the computer shader, it is declared:

ByteAddressBuffer              RawImage    : register(t0);
RWTexture2D<float4>            Output      : register(u0);

Output is a texture2D which is rendered on screen. The ByteAddressBuffer is used like this:

Value   = RawImage.Load4(0);
Color.b = Value[0];
Color.g = Value[1];
Color.r = Value[2];
Color.a = 1;
Output[DTid.xy] = Color;

On the display I only see white while the RGB value is (226, 200, 170) which is blue sky.

You probably need to see the full code, I have prepared a zip file with a complete MSVC2015 solution. Download here: BIPApplication.zip

Any help appreciated.

1
I wonder is Load4() will return the 4 bytes of a single location in the ByteAddressBuffer or if it returns 4 consecutives 32 bits integers. The documentation is not very clear to me. Nevertheless, I also tried Load() to get a single 32 bit integer and then use shift and mask to extract 3 bytes from it. Same bad result.fpiette
SOLVED: I've found the issue. I was not at all a problem of initializing the raw buffer, it was in the shader, in the way I interpret the bytes and the colors. Colors components are actually float between 0 and 1 inclusive. Load4() returns 4 consecutives integers. That is not what I need. I need to use one Load() to get one integer and then use shift and mask to extract the correct byte from the 32 bit integer.fpiette

1 Answers

0
votes

I've found the issue. I was not at all a problem of initializing the raw buffer, it was in the shader, in the way I interpret the bytes and the colors.

Colors components are actually float between 0 and 1 inclusive. Load4() returns 4 consecutives integers. That is not what I need. I need to use one Load() to get one integer and then use shift and mask to extract the correct byte from the 32 bit integer.