【发布时间】:2017-08-08 03:00:55
【问题描述】:
自从我上次提出问题以来,我已经取得了相当大的进步。我现在有了一个非常酷的构建,带有山脉和湖泊的地形网格: LakeAndMountains
我制作了一个发布版本,对其进行了调试,现在它在我的计算机上运行良好。我可以获取应用程序文件夹并在我的计算机上移动它并运行 .exe 文件而没有问题。但是,当我将应用程序目录复制到我的另一台计算机(和我朋友的计算机)时,它在 D3D11CreateDeviceAndSwapChain 步骤期间失败,HR 为 S_False。
对于我的另一台计算机和我朋友的计算机,它只在调用 create 函数后触发 if(failed(hr)),它说 dev/devcon/swapchain 都是 NULL。因为它们都是空的,所以当它从交换链中访问函数时,它会因访问冲突错误而崩溃。
我搜索了几天寻找解决方案,但我还没有看到发生 S_FALSE 的解决方案。我尝试了一些更直接的答案,但一无所获。所有计算机都在 64 位操作系统上运行 64 位,都具有 DirectX12,都是高端游戏 PC,我的另一台计算机实际上具有 VS2017CE 以及为 C++ 游戏编程设置,但它们仍然在那条线上失败。如果有人能给我一些关于从哪里开始解读为什么发布版本可以在我的计算机上运行但不能在其他任何人的计算机上运行的指导,我将非常感激。这是初始化的代码,以及创建窗口的代码(代码仅摘录到函数的相关部分):
WinMain:
// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
//MessageBox(NULL, "Start of WinMain", "WinMain", 0);
// the handle for the window, filled by a function
HWND hWnd;
// this struct holds information for the window class
WNDCLASSEX wc;
//Screen size variables
long screenWidth = 1280;
long screenHeight = 720;
UINT screenWidthUINT = 1280;
UINT screenHeightUINT = 720;
// clear out the window class for use
ZeroMemory(&wc, sizeof(WNDCLASSEX));
// fill in the struct with the needed information
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
//wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = "WindowClass1";
// register the window class
RegisterClassEx(&wc);
RECT wr = { 0, 0, screenWidth, screenHeight }; // set the size, but not the position
AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); // adjust the size
// create the window and use the result as the handle
hWnd = CreateWindowEx(NULL,
"WindowClass1",
"Game",
WS_OVERLAPPEDWINDOW,
0, // x-position of the window
0, // y-position of the window
wr.right - wr.left, // width of the window
wr.bottom - wr.top, // height of the window
NULL,
NULL,
hInstance,
NULL);
// display the window on the screen
ShowWindow(hWnd, nCmdShow);
//MessageBox(NULL, "called ShowWindow", "WinMain", 0);
/*****************************************
// GAME ENGINE INITIALIZATION
******************************************/
//Need to initialize the graphics engine. This passes the window pointer through the
//game engine to the D3D engine so it knows what window to look at.
//MessageBox(NULL, "Calling InitGraphics", "WinMain", 0);
InitGraphics(hWnd);
初始化图形:
//DEVICE CREATION
#include Windows.h
#include <windowsx.h>
#include <d3d11.h>
#include <DirectXMath.h>
#include <D3Dcompiler.h>
#include <dxgi.h>
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "d3dcompiler.lib")
#include "DirectXDeviceEngine.h"
using namespace DirectX;
InitGraphics(HWND hWnd)
{
//call at start to initialize D3DX
if (hWnd == NULL)
{
MessageBox(NULL, "hWnd was NULL", "DirectXDeviceEngine", 0);
}
HRESULT hr;
//initialize swap chain
//Describe our Buffer
DXGI_MODE_DESC bufferDesc;
ZeroMemory(&bufferDesc, sizeof(DXGI_MODE_DESC));
bufferDesc.Width = winWidth;
bufferDesc.Height = winHeight;
bufferDesc.RefreshRate.Numerator = 60;
bufferDesc.RefreshRate.Denominator = 1;
bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
// create a struct to hold information about the swap chain
DXGI_SWAP_CHAIN_DESC scd;
// clear out the struct for use
ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
// fill the swap chain description struct
scd.BufferCount = 1; // one back buffer
scd.BufferDesc = bufferDesc;
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // how swap chain is to be used
scd.OutputWindow = hWnd; // the window to be used
scd.SampleDesc.Count = 4; // how many multisamples
scd.SampleDesc.Quality = 1;
scd.Windowed = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; // windowed/full-screen mode
scd.Flags = 0;
// create a device, device context and swap chain using the information in the scd struct
dev = NULL;
devcon = NULL;
swapchain = NULL;
hr = D3D11CreateDeviceAndSwapChain(
NULL, //null
D3D_DRIVER_TYPE_HARDWARE, //driver type
NULL, //handle to a software rasterizer, should be null if driver type isn't software
NULL, //UINT device creation flags, can be ORed together
NULL, //D3D Feature level, when NULL defaults to 11.0-9.1 feature levels
NULL, //the number of elements in the D3D feature level array
D3D11_SDK_VERSION, //set to D3D11_SDK_VERSION
&scd, //reference to the swap chain desc
&swapchain, //reference to the pointer to the swap chain
&dev, //reference to the pointer to the device
NULL, //returns a reference to the first supported element in the feature level array
&devcon); //reference to the pointer to the device context
if (FAILED(hr))
{
//CODE FALLS INTO THIS BLOCK ON OTHER COMPUTER
MessageBox(NULL, "Create Device and SwapChain FAILED", "DirectXDeviceEngine", 0);
if (swapchain == NULL)
{
MessageBox(NULL, "swapchain was NULL", "DirectXDeviceEngine", 0);
}
if (dev == NULL)
{
MessageBox(NULL, "dev was NULL", "DirectXDeviceEngine", 0);
}
if (devcon == NULL)
{
MessageBox(NULL, "devcon was NULL", "DirectXDeviceEngine", 0);
}
}
//prepare buffers
// get the address of the back buffer
ID3D11Texture2D *pBackBuffer;
//VVVV CODE THEN CRASHES ON NEXT LINE BECAUSE SWAPCHAIN IS NULL VVVV
swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
提前致谢。
----2017/09/08 更新----- 所以我交换了一些代码,但我仍然在另一台计算机上收到错误。当前代码如下所示:
//call at start to initialize D3DX
if (&hWnd == NULL)
{
MessageBox(NULL, "hWnd was NULL", "DirectXDeviceEngine", 0);
}
HRESULT hr;
// create a device, device context and swap chain using the information in the scd struct
dev = NULL;
devcon = NULL;
swapchain = NULL;
D3D_FEATURE_LEVEL lvl[] = {
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_2, D3D_FEATURE_LEVEL_9_1 };
DWORD createDeviceFlags = 0;
hash ifdef _DEBUG
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
hash endif
D3D_FEATURE_LEVEL fl;
hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr,
createDeviceFlags, lvl, _countof(lvl),
D3D11_SDK_VERSION, &dev, &fl, &devcon);
if (hr == E_INVALIDARG)
{
hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr,
createDeviceFlags, &lvl[1], _countof(lvl) - 1,
D3D11_SDK_VERSION, &dev, &fl, &devcon);
}
if (FAILED(hr))
{
MessageBox(NULL, "Create Device Failed", "DirectXDeviceEngine", 0);
}
IDXGIDevice * dxgiDevice = 0;
dev->QueryInterface(__uuidof(IDXGIDevice), (void **)& dxgiDevice);
IDXGIAdapter * dxgiAdapter = 0;
dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void **)& dxgiAdapter);
IDXGIFactory * dxgiFactory = 0;
dxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void **)& dxgiFactory);
//initialize swap chain
//Describe our Buffer
DXGI_MODE_DESC bufferDesc;
ZeroMemory(&bufferDesc, sizeof(DXGI_MODE_DESC));
/*bufferDesc.Width = winWidth;
bufferDesc.Height = winHeight;
bufferDesc.RefreshRate.Numerator = 60;
bufferDesc.RefreshRate.Denominator = 1;
*/
bufferDesc.Width = 0;
bufferDesc.Height = 0;
bufferDesc.RefreshRate.Numerator = 0;
bufferDesc.RefreshRate.Denominator = 1;
bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
// create a struct to hold information about the swap chain
DXGI_SWAP_CHAIN_DESC scd;
// clear out the struct for use
ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
// fill the swap chain description struct
scd.BufferCount = 1; // one back buffer
scd.BufferDesc = bufferDesc;
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // how swap chain is to be used
scd.OutputWindow = hWnd; // the window to be used
scd.SampleDesc.Count = 4; // how many multisamples
scd.SampleDesc.Quality = 1;
scd.Windowed = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; // windowed/full-screen mode
scd.Flags = 0;
hr = dxgiFactory->CreateSwapChain(dev, &scd, &swapchain);
if (FAILED(hr))
{
//fails here
MessageBox(NULL, "Create Swap Chain Failed", "DirectXDeviceEngine", 0);
}
if (dxgiDevice != NULL)
{
dxgiDevice->Release();
}
if (dxgiAdapter != NULL)
{
dxgiAdapter->Release();
}
if (dxgiFactory != NULL)
{
dxgiFactory->Release();
}
//prepare buffers
// get the address of the back buffer
ID3D11Texture2D *pBackBuffer;
swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
所以,这里仍然发生了一些奇怪的事情,我没有得到。如果有人有如何正确使用 FindClosestMatchingMode 的示例,我将不胜感激。
不过,还有另一件非常奇特的事情。当我在笔记本电脑的调试器中时,变量 hWnd 有一个值,但编译器说它是未使用的,无法显示它的值。这是正常的还是可能是问题的根源,因为在交换链描述中使用了 hWnd? hWnd 怎么会在另一台计算机上坏/未使用,但在我的桌面上却没有?
再次感谢。
【问题讨论】:
-
看起来它失败了,因为您在调用 D3D11CreateDeviceAndSwapChain 时没有指定有效的创建标志。如果您查看此枚举 D3D11_CREATE_DEVICE_FLAG 它没有任何等于 0 的值:msdn.microsoft.com/en-us/library/windows/desktop/… 如果您不使用延迟设备上下文,那么至少指定 D3D11_CREATE_DEVICE_SINGLETHREADED,可能会解决您的问题
-
我刚才试过了,但我得到了同样的错误,S_FALSE 在小时返回,没有其他信息。这很奇怪,因为该版本在我的计算机上运行得很好,但当我将它移到另一台计算机时却不行。这也很奇怪,因为我可以将发布文件夹移动到其他地方,它在我的 comp 上仍然可以正常工作。
-
0 是创建标志的有效值,尽管您不应该真正将
NULL用于值 0。这当然是 C++11 强烈鼓励使用 @987654328 的原因@ 而不是旧版NULL,这会为非指针用法生成错误/警告。 -
您是否尝试过在受影响的系统上启用
D3D11_CREATE_DEBUG_FLAG并寻找输出?一般来说D3D11CreateDeviceAndSwapChain是一个较旧的遗留函数;有关现代设备创建的详细信息,请参阅Anatomy of Direct3D 11 Create Device。 -
请注意,
S_FALSE仍被视为成功返回(使用SUCCEEDED宏会通过测试,而使用FAILED不会通过测试)。我不确定在这种情况下它到底意味着什么,但我怀疑它与使用全屏独占模式和 MSAA 有关:也许它正在创建一个具有“关闭”模式的交换链,而不是刷新率经常发生的精确匹配.
标签: c++ directx-11