1
\$\begingroup\$
    D3D11_TEXTURE2D_DESC texDesc;
    texDesc.ArraySize = 1;
    texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
    texDesc.CPUAccessFlags = 0;
    texDesc.Format = DXGI_FORMAT_R32G32B32_FLOAT;
    texDesc.Width = width;
    texDesc.Height = height;
    texDesc.MipLevels = 0;
    texDesc.MiscFlags = 0;
    texDesc.SampleDesc.Count = 1;
    texDesc.SampleDesc.Quality = 0;
    texDesc.Usage = D3D11_USAGE_DEFAULT;

    D3D11_SUBRESOURCE_DATA data;
    data.pSysMem = finalData.data();
    data.SysMemPitch = width * 3 * sizeof(float);
    data.SysMemSlicePitch = finalData.size() * sizeof(float);

    HRESULT hr = device->CreateTexture2D(&texDesc, &data, &texture);

I just can't see what's wrong. I am absolutely certain that the vector is properly initialized, that there is three floats per pixel and that the width is the given width. What's wrong? And the vector is of type float.

I've tried zeroing out the subresource data and just setting pSysMem, but no go.

Please help.

\$\endgroup\$
4
\$\begingroup\$

So, you've probably read this:

MipLevels Type: UINT

The maximum number of mipmap levels in the texture. See the remarks in D3D11_TEX1D_SRV. Use 1 for a multisampled texture; or 0 to generate a full set of subtextures.

Yay, DirectX is going to do the dirty work for once! Hah. The devil is in the details. How so? Well, it said it is going to generate a full set of subtextures. It will figure out how many subtextures are needed from your width x height to the smallest — and generate the subtextures. But it won't fill them with anything, even though it has the 0th level source texture.

It is going to expect you to provide D3D11_SUBRESOURCE_DATA data[n] from the biggest (source) mipmap to the smallest, as the runtime would tell you in your output window if you created the device in debug mode. Yes, that means you need to prefilter as many levels as there are needed and give a proper data pointer and pitches for each of them.

On one unapplicable misc flag

You've heard about D3D11_RESOURCE_MISC_GENERATE_MIPS and wonder if it applies because you could call ID3D11DeviceContext::GenerateMips? Unfortunately, Direct3D requires it to be bindable as a render target AND a shader resource. This originates in the interesting decision to only allow for mipmap automation when a texture is used as a render target, as it is not filled by the user.

So, maybe set it as a render target even though you'll never use it in that capacity? Besides it being dirty, you're out of luck again, as DXGI_FORMAT_R32G32B32_FLOAT is not a valid render target format.

Summary

You cannot have your cake and eat it. Prefilter your texture to as many levels as needed and then fill out the D3D11_SUBRESOURCE_DATA for each one of them and pass it in bulk to the CreateTexture2D.

In the end, as much as it is sneaky, Direct3D did its job. It generated the subtextures. It said nothing about filling them with filtered data from your source texture.

\$\endgroup\$

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.