【问题标题】:DirectX 11 ID3DDevice::CreateTexture2D with initial data failDirectX 11 ID3DDevice::CreateTexture2D 初始数据失败
【发布时间】:2022-03-22 18:22:24
【问题描述】:

这么久我遵循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 并且此函数在设备上下文中

【问题讨论】:

  • 启用Direct3D Debug Device,您将从调试输出中获得更多关于它返回E_INVALIDARG的详细信息。

标签: directx directx-11


【解决方案1】:

我认为它失败的原因是您请求了无法使用初始数据设置的自动生成 mipmap (D3D11_RESOURCE_MISC_GENERATE_MIPS)。您必须改为通过设备上下文加载顶层。

有关自动生成 mipmap 的完整实现以及在其他场景中使用 initData,请参阅 DirectX Tool Kit 中的 WICTextureLoader

如果您使用 Direct3D 调试设备,它会在返回 E_INVALIDARG 时在输出窗口中提供更多详细信息。

【讨论】:

  • 非常感谢。我让调试设备工作,现在得到更多详细信息,我更新帖子以显示我发现的更多信息。
【解决方案2】:

我认为问题在于您为 D3D11_SUBRESOURCE_DATA::SysMemSlicePitch 字段分配了一个非零值,该字段仅对 3d 纹理有意义,对于其他纹理类型应设置为 0。在第一个示例中,您在调用 UpdateSubresource 时正确地将 0 作为类似参数的值传递。

【讨论】:

  • 嗨,我把它改成 0 但还是一样的错误信息
猜你喜欢
  • 2019-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-04
  • 2022-08-24
  • 1970-01-01
  • 2023-02-01
相关资源
最近更新 更多