微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

创建或更新 DirectX11 纹理会导致访问冲突异常

如何解决创建或更新 DirectX11 纹理会导致访问冲突异常

我正在尝试进行一个简单的测试,以更好地了解 DirectX11 以及如何使用 ID3D11Texture2D

我愿意从 ID3D11Texture2D 创建一个 unsigned char[],但由于某种原因它给了我以下错误

Exception thrown at 0x00007FFBBCB9C21E (nvwgf2umx.dll) in TestDX.exe: 0xC0000005: Access violation reading location 0x0000024B1A7A4000.

我创建了带有调试标志的 D3D11CreateDevice,但它没有显示更多有用的信息。

在互联网上查找后,this topic 建议我的 D3D11_TEXTURE2D_DESC Format 属性与输入数据格式不匹配。

为了重现,这是我的代码

const int width = 1920;
const int height = 1080;

unsigned char* pixels = new unsigned char[width * height * 4];

int numPixels = (int)(width * height);

// Setting up pixels
for (int i = 0; i < numPixels; i++) 
{
    *(pixels) = 255;
    *(pixels + 1) = 255;
    *(pixels + 2) = 255;
    *(pixels + 3) = 255;
    pixels += 4; // move the pointer along to the next rgba pixel
}

// Creating DirectX11 Device
UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_DEBUG;

D3D_FEATURE_LEVEL featureLevels[] =
{
    D3D_FEATURE_LEVEL_11_1,D3D_FEATURE_LEVEL_11_0,D3D_FEATURE_LEVEL_10_1,D3D_FEATURE_LEVEL_10_0,D3D_FEATURE_LEVEL_9_3,D3D_FEATURE_LEVEL_9_1
};

ID3D11Texture2D* tex = nullptr;
ID3D11Device* device = nullptr;
ID3D11DeviceContext* context = nullptr; 

if (Failed(D3D11CreateDevice(
    nullptr,// specify nullptr to use the default adapter
    D3D_DRIVER_TYPE_HARDWARE,nullptr,// specify nullptr because D3D_DRIVER_TYPE_HARDWARE 
                                // indicates that this function uses hardware
    creationFlags,// optionally set debug and Direct2D compatibility flags
    featureLevels,ARRAYSIZE(featureLevels),D3D11_SDK_VERSION,// always set this to D3D11_SDK_VERSION
    &device,&context)))
{
    cout << "Failed creating device" << endl;
    return 0;
}
else
{
    cout << "Created device" << endl;
}

D3D11_SUBRESOURCE_DATA initData = { 0 };
initData.pSysMem = (const void*)pixels;
initData.SysMemPitch = width * 4 * sizeof(unsigned char);
initData.SysMemSlicePitch = height * width * 4;

D3D11_TEXTURE2D_DESC tex_desc = {};
tex_desc.Height = height;
tex_desc.Width = width;
tex_desc.MipLevels = 1;
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;

HRESULT hres = device->CreateTexture2D(&tex_desc,&initData,&tex); // Causes exception

if (Failed(hres))
{
    cout << "Could not create texture" << endl;
    return 0;
}
else
{
    cout << "Created texture" << endl;
}

if (tex)
{
    tex->Release();
}

我也尝试创建一个空的纹理并使用 UpdateSubresource 作为某人在互联网上的建议并创建了这个场景:

const int width = 1920;
const int height = 1080;

unsigned char* pixels = new unsigned char[width * height * 4];

int numPixels = (int)(width * height);

// Setting up pixels
for (int i = 0; i < numPixels; i++)
{
    *(pixels) = 255;
    *(pixels + 1) = 255;
    *(pixels + 2) = 255;
    *(pixels + 3) = 255;
    pixels += 4; // move the pointer along to the next rgba pixel
}

// Creating DirectX11 Device
UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_DEBUG;

D3D_FEATURE_LEVEL featureLevels[] =
{
    D3D_FEATURE_LEVEL_11_1,D3D_FEATURE_LEVEL_9_1
};

ID3D11Texture2D* tex = nullptr;
ID3D11Device* device = nullptr;
ID3D11DeviceContext* context = nullptr;

if (Failed(D3D11CreateDevice(
    nullptr,&context)))
{
    cout << "Failed creating device" << endl;
    return 0;
}
else
{
    cout << "Created device" << endl;
}

D3D11_TEXTURE2D_DESC tex_desc = {};
tex_desc.Height = height;
tex_desc.Width = width;
tex_desc.MipLevels = 1;
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;

HRESULT hres = device->CreateTexture2D(&tex_desc,NULL,&tex);

if (Failed(hres))
{
    cout << "Could not create texture" << endl;
    return 0;
}
else
{
    cout << "Created texture" << endl;
}

int row_pitch = (width * 4) * sizeof(unsigned char);

context->UpdateSubresource(tex,pixels,row_pitch,0); // Causes exception

if (tex)
{
    tex->Release();
}

但是,这两种情况都会导致相同的异常,我认为这表明我的输入数据实际上是错误的,但我不明白为什么会出错。我的 pixels 确实代表了一个 RGBA 图像,我设置了 tex_desc.Format = dxgi_FORMAT_R8G8B8A8_UnorM,这看起来对我来说是正确的,但我对此完全没有经验,所以我无法真正判断。

我将不胜感激。

解决方法

这与 DirectX 无关,您的代码修改了原始的 pixels 指针(pixels++ 等),因此它传递垃圾(并最终指向锁定/未分配的操作系统内存页面,因为它是一个大缓冲区)作为初始数据,因此崩溃。

因此,例如,更改此内容:

unsigned char* pixels = new unsigned char[width * height * 4];

为此:

unsigned char* pixels = new unsigned char[width * height * 4];
unsigned char* mem = pixels;

并更改此:

initData.pSysMem = (const void*)pixels;

为此:

initData.pSysMem = (const void*)mem;

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。