代码之家  ›  专栏  ›  技术社区  ›  Elad Maimoni

无法从Direct3D 11中的内存正确初始化2D纹理

  •  1
  • Elad Maimoni  · 技术社区  · 7 年前

    我试图在系统内存中生成一个简单的数组,表示R8G8B8A8纹理,然后将该纹理传输到GPU内存。

    首先,我分配一个数组并用所需的绿色数据填充它:

        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;
    

    然后,我创建纹理对象并将其设置为像素着色器资源:

        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);
    

    我的期望是GPU内存将包含3x1绿色纹理,每个纹理在alpha通道中将有1.0f。但是,这不是通过Visual Studio图形调试器检查加载的纹理对象可以看到的情况:

    enter image description here

    有人能解释一下发生了什么事吗?我怎样才能解决这个问题?

    1 回复  |  直到 7 年前
        1
  •  4
  •   Nico Schertler    7 年前

    让我们看看您的阵列寻址方案(索引随着您提供的维数而减少):

    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;
    

    重新订购,我们得到

    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
    

    如您所见,这正是调试器向您显示的数据。

    所以你只需要修改你的地址方案。正确的公式是:

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

    pitch = width * components
    

    为了推导这个公式,您只需要考虑当您增加一个变量时,您必须跳过多少个索引。E、 g.当您增加当前组件时,只需进一步增加一个条目(因为所有组件彼此相邻)。另一方面,如果增加y坐标,则需要跳过与行中相同数量的条目(称为间距,即图像宽度乘以密集堆积的组件数)。