Failing to properly initialize a 2D texture from memory in Direct3D 11

白昼怎懂夜的黑 提交于 2021-02-10 15:28:13

问题


I am trying to produce a simple array in system memory that represent a R8G8B8A8 texture and than transfer that texture to the GPU memory.

First, I allocate an array and fill it with the desired green color data:

    frame.width = 3;
    frame.height = 1;
    auto components = 4;
    auto length = components * frame.width * frame.height;
    frame.data = new uint8_t[length];

    frame.data[0 + 0 * frame.width] = 0;  frame.data[1 + 0 * frame.width] = 255;  frame.data[2 + 0 * frame.width] = 0;  frame.data[3 + 0 * frame.width] = 255;
    frame.data[0 + 1 * frame.width] = 0;  frame.data[1 + 1 * frame.width] = 255;  frame.data[2 + 1 * frame.width] = 0;  frame.data[3 + 1 * frame.width] = 255;
    frame.data[0 + 2 * frame.width] = 0;  frame.data[1 + 2 * frame.width] = 255;  frame.data[2 + 2 * frame.width] = 0;  frame.data[3 + 2 * frame.width] = 255;

Then, I create the texture object and set it as the pixel shader resource:

    D3D11_TEXTURE2D_DESC textureDescription;

    textureDescription.Width = frame.width;
    textureDescription.Height = frame.height;

    textureDescription.MipLevels = textureDescription.ArraySize = 1;
    textureDescription.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
    textureDescription.SampleDesc.Count = 1;
    textureDescription.SampleDesc.Quality = 0; 
    textureDescription.Usage = D3D11_USAGE_DYNAMIC;
    textureDescription.BindFlags = D3D11_BIND_SHADER_RESOURCE;
    textureDescription.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    textureDescription.MiscFlags = 0;


    D3D11_SUBRESOURCE_DATA initialTextureData;
    initialTextureData.pSysMem = frame.data;
    initialTextureData.SysMemPitch = frame.width * components;
    initialTextureData.SysMemSlicePitch = 0;

    DX_CHECK(m_device->CreateTexture2D(&textureDescription, &initialTextureData, &m_texture));
    DX_CHECK(m_device->CreateShaderResourceView(m_texture, NULL, &m_textureView));
    m_context->PSSetShaderResources(0, 1, &m_textureView);

My expectation is that the GPU memory will contain a 3x1 green texture and that each texel will have 1.0f in the alpha chanel. However, this is not the case as can be viewed by examining the loaded texture object via the Visual Studio Graphics Debugger:

Could someone explain what is happening? How can I fix this?


回答1:


Let's take a look at your array addressing scheme (indices are reduced with the dimensions you provided):

frame.data[0] = 0;  frame.data[1] = 255;  frame.data[2] = 0;  frame.data[3] = 255;
frame.data[3] = 0;  frame.data[4] = 255;  frame.data[5] = 0;  frame.data[6] = 255;
frame.data[6] = 0;  frame.data[7] = 255;  frame.data[8] = 0;  frame.data[9] = 255;

Re-ordering, we get

data[ 0] = 0                  B pixel 1
data[ 1] = 255                G pixel 1
data[ 2] = 0                  R pixel 1
data[ 3] = 0  (overwritten)   A pixel 1
data[ 4] = 255                  pixel 2
data[ 5] = 0
data[ 6] = 0
data[ 7] = 255
data[ 8] = 0                    pixel 3
data[ 9] = 255
data[10] = undefined
data[11] = undefined

As you see, this is exactly the data that your debugger shows you.

So you just need to modify your adressing scheme. The correct formula would be:

index = component + x * components + y * pitch,

where you defined a dense packing with

pitch = width * components

In order to derive this formula, you just need to think about how many indices you have to skip when you increase one of the variables. E.g. when you increase the current component, you just need to step one entry further (because all components are right next to each other). On the other hand, if you increase the y-coordinate, you need to skip as many entries as there are in a row (this is called the pitch, which is the width of the image multiplied by the number of components for a dense packing).



来源:https://stackoverflow.com/questions/47030359/failing-to-properly-initialize-a-2d-texture-from-memory-in-direct3d-11

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!