问题
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