DirectX11--ComPtr智能指针
综述DirectX11 With Windows SDK完整目录 欢迎加入QQ群: 727623616 可以一起探讨DX11,以及有什么问题也可以在这里汇报。 IUnknown接口类DirectX11的API是由一系列的COM组件来管理的,这些前缀带I的接口类最终都继承自
在实际的使用情况来看,通常我们几乎不会使用第一个方法。而用的最多的就是第三个方法了,每次用完该实例后,我们必须要使用类似下面的宏来释放: #define ReleaseCOM(x) { if(x){ x->Release(); x = nullptr; } } 而且如果出现了忘记释放某个接口指针的情况话,内存泄漏的提醒就有可能够你去调试一整天了。 ComPtr智能指针为了解决上述问题,从繁杂的人工释放中解脱,在本教程中大量使用了 使用该智能指针需要包含头文件 首先有五个比较常用的方法需要了解一下:
然后是一些运算符重载的方法:
个人建议,在使用该智能指针后就应该要避免使用 虽然替换成 下面的 class D3DApp { public: D3DApp(HINSTANCE hInstance); // 在构造函数的初始化列表应当设置好初始参数 virtual ~D3DApp(); HINSTANCE AppInst()const; // 获取应用实例的句柄 HWND MainWnd()const; // 获取主窗口句柄 float AspectRatio()const; // 获取屏幕宽高比 int Run(); // 运行程序,进行游戏主循环 // 框架方法。客户派生类需要重载这些方法以实现特定的应用需求 virtual bool Init(); // 该父类方法需要初始化窗口和Direct3D部分 virtual void OnResize(); // 该父类方法需要在窗口大小变动的时候调用 virtual void UpdateScene(float dt) = 0; // 子类需要实现该方法,完成每一帧的更新 virtual void DrawScene() = 0; // 子类需要实现该方法,完成每一帧的绘制 virtual LRESULT MsgProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam); // 窗口的消息回调函数 protected: bool InitMainWindow(); // 窗口初始化 bool InitDirect3D(); // Direct3D初始化 void CalculateFrameStats(); // 计算每秒帧数并在窗口显示 protected: HINSTANCE mhAppInst; // 应用实例句柄 HWND mhMainWnd; // 主窗口句柄 bool mAppPaused; // 应用是否暂停 bool mMinimized; // 应用是否最小化 bool mMaximized; // 应用是否最大化 bool mResizing; // 窗口大小是否变化 bool mEnable4xMsaa; // 是否开启4倍多重采样 UINT m4xMsaaQuality; // MSAA支持的质量等级 GameTimer mTimer; // 计时器 // 使用模板别名(C++11)简化类型名 template <class T> using ComPtr = Microsoft::WRL::ComPtr<T>; // DX11 ComPtr<ID3D11Device> md3dDevice; // D3D11设备 ComPtr<ID3D11DeviceContext> md3dImmediateContext; // D3D11设备上下文 ComPtr<IDXGISwapChain> mSwapChain; // D3D11交换链 // DX11.1 ComPtr<ID3D11Device1> md3dDevice1; // D3D11.1设备 ComPtr<ID3D11DeviceContext1> md3dImmediateContext1; // D3D11.1设备上下文 ComPtr<IDXGISwapChain1> mSwapChain1; // D3D11.1交换链 // 常用资源 ComPtr<ID3D11Texture2D> mDepthStencilBuffer; // 深度模板缓冲区 ComPtr<ID3D11RenderTargetView> mRenderTargetView; // 渲染目标视图 ComPtr<ID3D11DepthStencilView> mDepthStencilView; // 深度模板视图 D3D11_VIEWPORT mScreenViewport; // 视口 // 派生类应该在构造函数设置好这些自定义的初始参数 std::wstring mMainWndCaption; // 主窗口标题 int mClientWidth; // 视口宽度 int mClientHeight; // 视口高度 }; 下面的代码演示了 bool D3DApp::InitDirect3D() { HRESULT hr = S_OK; // 创建D3D设备 和 D3D设备上下文 UINT createDeviceFlags = 0; #if defined(DEBUG) || defined(_DEBUG) createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; #endif // 驱动类型数组 D3D_DRIVER_TYPE driverTypes[] = { D3D_DRIVER_TYPE_HARDWARE,D3D_DRIVER_TYPE_WARP,D3D_DRIVER_TYPE_REFERENCE,}; UINT numDriverTypes = ARRAYSIZE(driverTypes); // 特性等级数组 D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_1,D3D_FEATURE_LEVEL_11_0,}; UINT numFeatureLevels = ARRAYSIZE(featureLevels); D3D_FEATURE_LEVEL featureLevel; D3D_DRIVER_TYPE d3dDriverType; for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++) { d3dDriverType = driverTypes[driverTypeIndex]; hr = D3D11CreateDevice(nullptr,d3dDriverType,nullptr,createDeviceFlags,featureLevels,numFeatureLevels,D3D11_SDK_VERSION,md3dDevice.GetAddressOf(),&featureLevel,md3dImmediateContext.GetAddressOf()); if (hr == E_INVALIDARG) { // DirectX 11.0 平台不承认D3D_FEATURE_LEVEL_11_1所以我们需要尝试特性等级11.0以及以下的版本 hr = D3D11CreateDevice(nullptr,&featureLevels[1],numFeatureLevels - 1,md3dImmediateContext.GetAddressOf()); } if (SUCCEEDED(hr)) break; } if (FAILED(hr)) { MessageBox(0,L"D3D11CreateDevice Failed.",0); return false; } // 检测是否支持特性等级11.0或11.1 if (featureLevel != D3D_FEATURE_LEVEL_11_0 && featureLevel != D3D_FEATURE_LEVEL_11_1) { MessageBox(0,L"Direct3D Feature Level 11 unsupported.",0); return false; } // 检测 MSAA支持的质量等级 md3dDevice->CheckMultisampleQualityLevels( DXGI_FORMAT_R8G8B8A8_UNORM,4,&m4xMsaaQuality); assert(m4xMsaaQuality > 0); ComPtr<IDXGIDevice> dxgiDevice = nullptr; ComPtr<IDXGIAdapter> dxgiAdapter = nullptr; ComPtr<IDXGIFactory1> dxgiFactory1 = nullptr; // DX11.0(包含DXGI1.1)的接口类 ComPtr<IDXGIFactory2> dxgiFactory2 = nullptr; // DX11.1(包含DXGI1.2)特有的接口类 // 为了正确创建 DXGI交换链,首先我们需要获取创建 D3D设备 的 DXGI工厂,否则会引发报错: // "IDXGIFactory::CreateSwapChain: This function is being called with a device from a different IDXGIFactory." // 从属关系为 DXGI工厂-> DXGI适配器 -> DXGI设备 {D3D11设备} HR(md3dDevice.As(&dxgiDevice)); HR(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf())); HR(dxgiAdapter->GetParent(__uuidof(IDXGIFactory1),reinterpret_cast<void**>(dxgiFactory1.GetAddressOf()))); // 查看该对象是否包含IDXGIFactory2接口 hr = dxgiFactory1.As(&dxgiFactory2); // 如果包含,则说明支持DX11.1 if (dxgiFactory2 != nullptr) { HR(md3dDevice.As(&md3dDevice1)); HR(md3dImmediateContext.As(&md3dImmediateContext1)); // 填充各种结构体用以描述交换链 DXGI_SWAP_CHAIN_DESC1 sd; ZeroMemory(&sd,sizeof(sd)); sd.Width = mClientWidth; sd.Height = mClientHeight; sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // 是否开启4倍多重采样? if (mEnable4xMsaa) { sd.SampleDesc.Count = 4; sd.SampleDesc.Quality = m4xMsaaQuality - 1; } else { sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; } sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.BufferCount = 1; sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; sd.Flags = 0; DXGI_SWAP_CHAIN_FULLSCREEN_DESC fd; fd.RefreshRate.Numerator = 60; fd.RefreshRate.Denominator = 1; fd.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; fd.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; fd.Windowed = TRUE; // 为当前窗口创建交换链 HR(dxgiFactory2->CreateSwapChainForHwnd(md3dDevice.Get(),mhMainWnd,&sd,&fd,mSwapChain1.GetAddressOf())); HR(mSwapChain1.As(&mSwapChain)); } else { // 填充DXGI_SWAP_CHAIN_DESC用以描述交换链 DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd,sizeof(sd)); sd.BufferDesc.Width = mClientWidth; sd.BufferDesc.Height = mClientHeight; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; // 是否开启4倍多重采样? if (mEnable4xMsaa) { sd.SampleDesc.Count = 4; sd.SampleDesc.Quality = m4xMsaaQuality - 1; } else { sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; } sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.BufferCount = 1; sd.OutputWindow = mhMainWnd; sd.Windowed = TRUE; sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; sd.Flags = 0; HR(dxgiFactory1->CreateSwapChain(md3dDevice.Get(),mSwapChain.GetAddressOf())); } // 可以禁止alt+enter全屏 dxgiFactory1->MakeWindowAssociation(mhMainWnd,DXGI_MWA_NO_ALT_ENTER | DXGI_MWA_NO_WINDOW_CHANGES); // 每当窗口被重新调整大小的时候,都需要调用这个OnResize函数。现在调用 // 以避免代码重复 OnResize(); return true; } DirectX11 With Windows SDK完整目录 欢迎加入QQ群: 727623616 可以一起探讨DX11,以及有什么问题也可以在这里汇报。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- wix – MSI主要升级覆盖规则
- 即使在Windows SBS中,也始终是通往互联网的路径
- windows – 如何访问虚拟机的IIS上托管的网站?
- Powershell:了解打印机DACL
- windows – WFPSampler编译问题 – 找不到wfpcalloutsclass
- 在Windows Sever2016中搭建DHCP服务为客户机提供ip地址
- Windows 7 – Windows 7:防止应用程序失去焦点
- windows-7 – 如何说服PowerShell(通过任务调度程序)找到我
- 在运行VM的Hyper-V服务器上运行Windows Update的最佳做法是
- active-directory – 用户在AD用户和计算机中不可见
- windows-server-2008-r2 – Windows 2008上注册的
- winapi – Win32在父窗口中捕获子窗口消息
- windows-server-2012-r2 – 服务器2012R2每周日早
- [转帖]Windows下cwRsyncServer双机连续同步部署
- windows-server-2003 – Windows Server 2003 –
- .net – SocketAsyncEventArgs.Completed在Windo
- .net – 在Windows应用程序中保存用户凭据
- 为什么我会收到多个同类窗口消息?
- Windows批处理文件 – 连接子目录中的所有文件
- windows-server-2008 – 设置Win2008 R2服务器 –