0
\$\begingroup\$

I am trying to make a full copy from a render target texture to a staging one but it seems my data length ends up being only 4 in length instead of 921600 (1280 * 720).

Here is my textures initializaion code :

// Setup the step count texture description.
D3D11_TEXTURE2D_DESC stepCountTextureDesc;
ZeroMemory(&stepCountTextureDesc, sizeof(stepCountTextureDesc));
stepCountTextureDesc.Width = g_clientWidth;
stepCountTextureDesc.Height = g_clientHeight;
stepCountTextureDesc.MipLevels = 1;
stepCountTextureDesc.ArraySize = 1;
stepCountTextureDesc.Format = DXGI_FORMAT_R32_UINT;
stepCountTextureDesc.SampleDesc.Count = 1;
stepCountTextureDesc.Usage = D3D11_USAGE_DEFAULT;
stepCountTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET;
stepCountTextureDesc.CPUAccessFlags = 0;
stepCountTextureDesc.MiscFlags = 0;

// Create the step count texture
hr = g_d3dDevice->CreateTexture2D(&stepCountTextureDesc, NULL, &g_StepCountTexture);
if (FAILED(hr)) return false;

// Setup the description of the render target views.
D3D11_RENDER_TARGET_VIEW_DESC stepCountRenderTargetViewDesc;
stepCountRenderTargetViewDesc.Format = stepCountTextureDesc.Format;
stepCountRenderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
stepCountRenderTargetViewDesc.Texture2D.MipSlice = 0;

// Create the render target view.
hr = g_d3dDevice->CreateRenderTargetView(g_StepCountTexture, &stepCountRenderTargetViewDesc, &g_StepCountRenderTargetView);
if (FAILED(hr)) return false;

// Setup the step count staging texture description.
D3D11_TEXTURE2D_DESC stepCountStagingTextureDesc;
ZeroMemory(&stepCountStagingTextureDesc, sizeof(stepCountTextureDesc));
stepCountStagingTextureDesc.Width = g_clientWidth;
stepCountStagingTextureDesc.Height = g_clientHeight;
stepCountStagingTextureDesc.MipLevels = 1;
stepCountStagingTextureDesc.ArraySize = 1;
stepCountStagingTextureDesc.Format = DXGI_FORMAT_R32_UINT;
stepCountStagingTextureDesc.SampleDesc.Count = 1;
stepCountStagingTextureDesc.Usage = D3D11_USAGE_STAGING;
stepCountStagingTextureDesc.BindFlags = 0;
stepCountStagingTextureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
stepCountStagingTextureDesc.MiscFlags = 0;

// Create the step count staging texture
hr = g_d3dDevice->CreateTexture2D(&stepCountStagingTextureDesc, NULL, &g_StepCountTextureStaging);
if (FAILED(hr)) return false;

Then the copy performed on each frame :

g_d3dDeviceContext->CopyResource(g_StepCountTextureStaging, g_StepCountTexture);
D3D11_MAPPED_SUBRESOURCE msr;
HRESULT hr = g_d3dDeviceContext->Map(g_StepCountTextureStaging, 0, D3D11_MAP_READ, 0, &msr);
if (FAILED(hr)) return;
g_StepCount = countSteps((BYTE*)msr.pData);
g_d3dDeviceContext->Unmap(g_StepCountTextureStaging, 0);

And the countSteps function :

unsigned int countSteps(BYTE* data) {
    return sizeof(data) / sizeof(data[0]); // -> 4 !?
}

The idea of the countSteps function is to iterate each texture pixel and add their unsigned int value together. The expected result would be above 1m, for now I get 17 sometimes 18 :)

How do I actually read my whole texture ?

\$\endgroup\$
1
\$\begingroup\$

There's three members of a D3D11_MAPPED_SUBRESOURCE:

  1. a pointer to the beginning of the data;
  2. the number of bytes from the beginning of one row of data to the next row of data;
  3. the number of bytes from the beginning of one depth slice of data to the next depth slice of data.

As none of these members communicate anything about the actual extents of a row of data, you need to query your texture resource for a DESC or remember the column and row counts from when you created it.

The 2D layout of the data is such that there are solid rows of data with the potential of padding at the end. The row pitch in the mapping indicate the offsets you need to use to jump between rows.

Assuming you know those quantities, you would iterate your mapped data similiar to this:

{
    uint32_t partialSum = 0u;
    // Point at the beginning of the first row
    BYTE const* rowPtr = msr.pData;
    for (size_t row = 0u; row < rows; ++row) {
        // Take the current row pointer and interpret as sequence of U32
        uint32_t const* p = reinterpret_cast<uint32_t const*>(rowPtr);
        for (size_t col = 0u; col < cols; ++col) {
            partialSum += *p;
            // Advance one U32
            ++p;
        }
        // Advance the row pointer to the beginning of the next row
        rowPtr += msr.RowPitch;
    }
}

The in-place reinterpret of the data is fine as feature levels 10_0 and up guarantee 16-byte alignment of mappings, and feature levels below guarantee 4-byte alignment, which is enough for U32. If this would not be the case, a byte-wise copy would have to be made into a properly aligned value on the CPU side before touching it.

\$\endgroup\$
  • \$\begingroup\$ My question actually boils down to : how do I read (BYTE*)msr.pData and sum all of it's elements ? \$\endgroup\$ – PinkTurtle Aug 27 '15 at 15:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.