只要我遵循的教程CreateTexture2D()
的初始数据为NULL,然后
使用UpdateSubresource()
加载数据,一切正常。但是UpdateSubResource()
是设备上下文函数,因此我尝试一次将CreateTexture2D()
与初始数据一起使用,但是失败。
下面的代码显示可以正常工作的原始文件。
tex_desc.Height = h;
tex_desc.Width = w;
tex_desc.MipLevels = 0;
tex_desc.ArraySize = 1;
tex_desc.Format= DXGI_FORMAT_R8G8B8A8_UNORM;
tex_desc.SampleDesc.Count = 1;
tex_desc.SampleDesc.Quality = 0;
tex_desc.Usage= D3D11_USAGE_DEFAULT;
tex_desc.BindFlags= D3D11_BIND_SHADER_RESOURCE|D3D11_BIND_RENDER_TARGET;
tex_desc.CPUAccessFlags= 0;
tex_desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;
row_pitch = (w * 4) * sizeof(unsigned char);
hres = _dv->CreateTexture2D(&tex_desc, NULL, &m_tex);
HR_FAIL(hres, "create 2D texture");
_dc->UpdateSubresource(m_tex, 0, NULL, data, row_pitch, 0);
然后我将其更改为
tex_desc.Height = h;
tex_desc.Width = w;
tex_desc.MipLevels = 0;
tex_desc.ArraySize = 1;
tex_desc.Format= DXGI_FORMAT_R8G8B8A8_UNORM;
tex_desc.SampleDesc.Count = 1;
tex_desc.SampleDesc.Quality = 0;
tex_desc.Usage= D3D11_USAGE_DEFAULT;
tex_desc.BindFlags= D3D11_BIND_SHADER_RESOURCE|D3D11_BIND_RENDER_TARGET;
tex_desc.CPUAccessFlags= 0;
tex_desc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;
row_pitch = (w * 4) * sizeof(unsigned char);
D3D11_SUBRESOURCE_DATA sdata; // <<===changed
sdata.pSysMem = data; // <<===changed
sdata.SysMemPitch = row_pitch; // <<===changed
sdata.SysMemSlicePitch = (w*h*4)*sizeof(unsigned char); // <<===changed
hres = _dv->CreateTexture2D(&tex_desc, &sdata, &m_tex); // <<===changed
HR_FAIL(hres, "testing create texture 2d");
然后它会产生错误
testing create texture 2d fail
E_INVALIDARG : An invalid parameter was passed to the returning function.
它说某些参数无效,但我不明白为什么我传递的参数无效
更新:
所以我尝试按照链接设置DirectX的调试设备。这是我得到的:
D3D11 ERROR: ID3D11Device::CreateTexture2D: pInitialData[4].SysMemPitch cannot be 0 [ STATE_CREATION ERROR #100: CREATETEXTURE2D_INVALIDINITIALDATA]
D3D11 ERROR: ID3D11Device::CreateTexture2D: pInitialData[6].pSysMem cannot be NULL. [ STATE_CREATION ERROR #100: CREATETEXTURE2D_INVALIDINITIALDATA]
D3D11 ERROR: ID3D11Device::CreateTexture2D: pInitialData[7].pSysMem cannot be NULL. [ STATE_CREATION ERROR #100: CREATETEXTURE2D_INVALIDINITIALDATA]
D3D11 ERROR: ID3D11Device::CreateTexture2D: Returning E_INVALIDARG, meaning invalid parameters were passed. [ STATE_CREATION ERROR #104: CREATETEXTURE2D_INVALIDARG_RETURN]
Exception thrown at 0x750BC54F in directx11_test.exe: Microsoft C++ exception: _com_error at memory location 0x002BF3D0.
D3D11 ERROR: ID3D11Device::CreateTexture2D: pInitialData[2].pSysMem cannot be NULL. [ STATE_CREATION ERROR #100: CREATETEXTURE2D_INVALIDINITIALDATA]
D3D11 ERROR: ID3D11Device::CreateTexture2D: pInitialData[4].SysMemPitch cannot be 0 [ STATE_CREATION ERROR #100: CREATETEXTURE2D_INVALIDINITIALDATA]
D3D11 ERROR: ID3D11Device::CreateTexture2D: pInitialData[6].pSysMem cannot be NULL. [ STATE_CREATION ERROR #100: CREATETEXTURE2D_INVALIDINITIALDATA]
D3D11 ERROR: ID3D11Device::CreateTexture2D: pInitialData[7].pSysMem cannot be NULL. [ STATE_CREATION ERROR #100: CREATETEXTURE2D_INVALIDINITIALDATA]
D3D11 ERROR: ID3D11Device::CreateTexture2D: Returning E_INVALIDARG, meaning invalid parameters were passed. [ STATE_CREATION ERROR #104: CREATETEXTURE2D_INVALIDARG_RETURN]
因此它说Create函数尝试将InitialData作为数组访问,而我只有一个元素作为参数传递。 需要注意的一件事是,我仅在发布配置中获得调试输出(我在代码中手动定义了_DEBUG)。在“调试配置”中,我获得了访问冲突异常触发器,因此未收到D3D调试消息。
所以我有一种解决方法,就是得到一个足够大的子资源数组,以存储各种类型的mipmap级别,以防止访问冲突。
D3D11_SUBRESOURCE_DATA sdata[20];
int idx = 0;
while (row_pitch > 0)
{
sdata[idx].pSysMem = data;
sdata[idx].SysMemPitch = row_pitch;
row_pitch >>= 1;
idx++;
}
hres = _dv->CreateTexture2D(&tex_desc, sdata, &m_tex);
HR_FAIL(hres, "testing create texture 2d");
但是我认为这是不明智的,因为我仍然需要生成mipmap且此功能在设备上下文中
答案 0 :(得分:1)
我相信失败的原因是您请求了自动生成的mipmap(D3D11_RESOURCE_MISC_GENERATE_MIPS
),您不能使用初始数据进行设置。您必须改为通过设备上下文加载顶层。
有关自动生成mipmap的完整实现以及在其他情况下使用initData的信息,请参见WICTextureLoader中的DirectX Tool Kit
如果使用Direct3D调试设备,则在返回
E_INVALIDARG
时会在输出窗口中提供更多详细信息。
答案 1 :(得分:0)
我认为问题在于,您为D3D11_SUBRESOURCE_DATA::SysMemSlicePitch
字段分配了一个非零值,该值仅对3d纹理有意义,对于其他纹理类型应设置为0。在第一个示例中,您在调用UpdateSubresource
时正确地将0作为相似参数的值传递。