创建或更新 DirectX11 纹理会出现访问冲突异常
Creating or Updating DirectX11 texture gives Access Violation Exception
我正在尝试做一个简单的测试来更好地理解 DirectX11 以及如何使用 ID3D11Texture2D
。
我愿意从 unsigned char[]
创建一个 ID3D11Texture2D
,但由于某种原因它给我以下错误:
Exception thrown at 0x00007FFBBCB9C21E (nvwgf2umx.dll) in TestDX.exe: 0xC0000005: Access violation reading location 0x0000024B1A7A4000.
我创建了带有调试标志的 D3D11CreateDevice
,它没有显示任何更有用的信息。
在网上查找后, 表明我的 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,
nullptr,
&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_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,
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, 0, NULL, pixels, row_pitch, 0); // Causes exception
if (tex)
{
tex->Release();
}
然而,这两种情况都会导致相同的异常,我认为这表明我的输入数据实际上是错误的,但我不明白为什么会出错。我的 pixels
确实代表了一个 RGBA 图像,我设置了 tex_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM
,这对我来说看起来是正确的,但我对此一点经验都没有,所以我无法真正判断。
如有任何帮助,我将不胜感激。
这与 DirectX 无关,您的代码修改了原始 pixels
指针(pixels++
,等等)因此它传递垃圾(并最终指向 locked/unallocated OS 内存页面,因为它是一个大缓冲区)作为初始数据,因此崩溃。
所以,例如,改变这个:
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;
我正在尝试做一个简单的测试来更好地理解 DirectX11 以及如何使用 ID3D11Texture2D
。
我愿意从 unsigned char[]
创建一个 ID3D11Texture2D
,但由于某种原因它给我以下错误:
Exception thrown at 0x00007FFBBCB9C21E (nvwgf2umx.dll) in TestDX.exe: 0xC0000005: Access violation reading location 0x0000024B1A7A4000.
我创建了带有调试标志的 D3D11CreateDevice
,它没有显示任何更有用的信息。
在网上查找后,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,
nullptr,
&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_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,
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, 0, NULL, pixels, row_pitch, 0); // Causes exception
if (tex)
{
tex->Release();
}
然而,这两种情况都会导致相同的异常,我认为这表明我的输入数据实际上是错误的,但我不明白为什么会出错。我的 pixels
确实代表了一个 RGBA 图像,我设置了 tex_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM
,这对我来说看起来是正确的,但我对此一点经验都没有,所以我无法真正判断。
如有任何帮助,我将不胜感激。
这与 DirectX 无关,您的代码修改了原始 pixels
指针(pixels++
,等等)因此它传递垃圾(并最终指向 locked/unallocated OS 内存页面,因为它是一个大缓冲区)作为初始数据,因此崩溃。
所以,例如,改变这个:
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;