UINT D3D10System::GetNumOutputs() { UINT count = 0; IDXGIDevice *device; if(SUCCEEDED(d3d->QueryInterface(__uuidof(IDXGIDevice), (void**)&device))) { IDXGIAdapter *adapter; if(SUCCEEDED(device->GetAdapter(&adapter))) { IDXGIOutput *outputInterface; while(SUCCEEDED(adapter->EnumOutputs(count, &outputInterface))) { count++; outputInterface->Release(); } adapter->Release(); } device->Release(); } return count; }
bool DX11Engine::CreateSwapChain(HWND handle, UINT xSize, UINT ySize) { mXsize = xSize; mYSize = ySize; IDXGIDevice* dxgiDevice = nullptr; HRESULT hr = m_pDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice); if (hr != S_OK) { return false; } IDXGIAdapter* dxgiAdapter = nullptr; hr = dxgiDevice->GetAdapter(&dxgiAdapter); if (hr != S_OK) { return false; } IDXGIFactory1* dxgiFactory1 = nullptr; hr = dxgiAdapter->GetParent(__uuidof(IDXGIFactory1), (void**)&dxgiFactory1); if (hr != S_OK) { return false; } DXGI_SWAP_CHAIN_DESC desc; desc.BufferDesc.Width = xSize; desc.BufferDesc.Height = ySize; desc.BufferDesc.RefreshRate.Numerator = 0; desc.BufferDesc.RefreshRate.Denominator = 1; desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.BufferUsage = DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_RENDER_TARGET_OUTPUT; desc.BufferCount = 2; desc.OutputWindow = handle; desc.Windowed = TRUE; desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; desc.Flags = 0; hr = dxgiFactory1->CreateSwapChain(dxgiDevice, &desc, &m_pSwapChain); if (hr != S_OK) { return false; } dxgiDevice->Release(); dxgiAdapter->Release(); dxgiFactory1->Release(); return true; }
void DesktopDuplication::init() { IDXGIFactory1* dxgiFactory = nullptr; CHECKED(hr, CreateDXGIFactory1(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&dxgiFactory))); IDXGIAdapter1* dxgiAdapter = nullptr; CHECKED(hr, dxgiFactory->EnumAdapters1(adapter, &dxgiAdapter)); dxgiFactory->Release(); CHECKED(hr, D3D11CreateDevice(dxgiAdapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, NULL, NULL, NULL, D3D11_SDK_VERSION, &d3dDevice, NULL, &d3dContext)); IDXGIOutput* dxgiOutput = nullptr; CHECKED(hr, dxgiAdapter->EnumOutputs(output, &dxgiOutput)); dxgiAdapter->Release(); IDXGIOutput1* dxgiOutput1 = nullptr; CHECKED(hr, dxgiOutput->QueryInterface(__uuidof(dxgiOutput1), reinterpret_cast<void**>(&dxgiOutput1))); dxgiOutput->Release(); IDXGIDevice* dxgiDevice = nullptr; CHECKED(hr, d3dDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice))); CHECKED(hr, dxgiOutput1->DuplicateOutput(dxgiDevice, &outputDuplication)); dxgiOutput1->Release(); dxgiDevice->Release(); }
void D3DContext::InitD3D(HWND hWnd) { m_MSAAEnabled = true; HRESULT hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, m_DebugLayerEnabled ? D3D11_CREATE_DEVICE_DEBUG : D3D11_CREATE_DEVICE_SINGLETHREADED, NULL, NULL, D3D11_SDK_VERSION, &dev, &m_D3DFeatureLevel, &devcon); dev->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, 4, &m_MSAAQuality); // assert(m_MSAAQuality > 0); DXGI_SWAP_CHAIN_DESC scd; ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC)); scd.BufferDesc.Width = m_Properties.width; scd.BufferDesc.Height = m_Properties.height; scd.BufferDesc.RefreshRate.Numerator = 60; scd.BufferDesc.RefreshRate.Denominator = 1; scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; scd.SampleDesc.Count = m_MSAAEnabled ? 4 : 1; scd.SampleDesc.Quality = m_MSAAEnabled ? (m_MSAAQuality - 1) : 0; scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; scd.BufferCount = 3; scd.OutputWindow = hWnd; scd.Windowed = !m_Properties.fullscreen; scd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; IDXGIDevice* dxgiDevice = 0; IDXGIAdapter* dxgiAdapter = 0; IDXGIFactory* dxgiFactory = 0; dev->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice); dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&dxgiAdapter); dxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&dxgiFactory); dxgiFactory->CreateSwapChain(dev, &scd, &swapchain); dxgiFactory->Release(); dxgiAdapter->Release(); dxgiDevice->Release(); if (m_DebugLayerEnabled) { dev->QueryInterface(__uuidof(ID3D11Debug), reinterpret_cast<void**>(&m_DebugLayer)); m_DebugLayer->ReportLiveDeviceObjects(D3D11_RLDO_SUMMARY); ID3D11InfoQueue* infoQueue; dev->QueryInterface(__uuidof(ID3D11InfoQueue), reinterpret_cast<void**>(&infoQueue)); D3D11_MESSAGE_ID hide[] = { D3D11_MESSAGE_ID_DEVICE_DRAW_SAMPLER_NOT_SET }; D3D11_INFO_QUEUE_FILTER filter; memset(&filter, 0, sizeof(filter)); filter.DenyList.NumIDs = 1; filter.DenyList.pIDList = hide; infoQueue->AddStorageFilterEntries(&filter); } Resize(); }
bool TRenderDevice::CreateSwapChain(){ IDXGIDevice* device; if (FAILED(Device->QueryInterface(__uuidof(IDXGIDevice), (void**) &device))){ MessageBox(0,L"获取设备接口失败",0,0); return false; } IDXGIAdapter* adapter; if (FAILED(device->GetParent(__uuidof(IDXGIAdapter), (void**) &adapter))){ MessageBox(0,L"获取适配器接口失败",0,0); return false; } IDXGIFactory* factory; if (FAILED(adapter->GetParent(__uuidof(IDXGIFactory), (void**) &factory))){ MessageBox(0,L"获取Factory接口失败",0,0); return false; } DXGI_SWAP_CHAIN_DESC sd; sd.BufferDesc.Width = RenderSize->GetRenderWidth(); sd.BufferDesc.Height = RenderSize->GetRenderHeight(); 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; if (MsaaQuality>0){ sd.SampleDesc.Count = MsaaQuality; sd.SampleDesc.Quality = MsaaQuality - 1; }else{ sd.SampleDesc.Count=1; sd.SampleDesc.Quality=0; } sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.BufferCount = 1; sd.OutputWindow = RenderWindow->GetHWnd(); sd.Windowed = true; sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; sd.Flags = 0; if (FAILED(factory->CreateSwapChain(Device, &sd, &SwapChain))){ MessageBox(0,L"创建SwapChain失败",0,0); return false; } device->Release(); adapter->Release(); factory->Release(); return true; }
std::shared_ptr<SwapChain> Device::createSwapChain(const Window& window) { std::shared_ptr<SwapChain> swapChain; IDXGIDevice* dxgiDevice = nullptr; if (SUCCEEDED(m_device->QueryInterface<IDXGIDevice>(&dxgiDevice))) { IDXGIAdapter* adapter = nullptr; if (SUCCEEDED(dxgiDevice->GetAdapter(&adapter))) { IDXGIFactory* dxgiFactory = nullptr; if (SUCCEEDED(adapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&dxgiFactory)))) { DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof(sd)); sd.BufferCount = 1; sd.BufferDesc.Width = window.getWidth(); sd.BufferDesc.Height = window.getHeight(); sd.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 0; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = window.getPlatformData()->getHandle(); sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; IDXGISwapChain* nativeSwapChain = nullptr; if (SUCCEEDED(dxgiFactory->CreateSwapChain(m_device, &sd, &nativeSwapChain))) { ID3D11Texture2D* backBufferTexture = nullptr; if (SUCCEEDED(nativeSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&backBufferTexture)))) { auto texture = std::make_shared<Texture2d>(backBufferTexture); auto backBufferRenderCommandEncoder = createRenderCommandEncoder(1, &texture, nullptr, false); swapChain = std::make_shared<SwapChain>(nativeSwapChain, backBufferRenderCommandEncoder); } dxgiFactory->Release(); } adapter->Release(); } } dxgiDevice->Release(); } return swapChain; }
// Callers must Release the DXGIAdapter after use or risk mem-leak static bool GetDXGIAdapter(__out IDXGIAdapter **DXGIAdapter) { ID3D10Device1 *D2D10Device; IDXGIDevice *DXGIDevice; bool result = false; if (D2D10Device = mozilla::gfx::Factory::GetDirect3D10Device()) { if (D2D10Device->QueryInterface(__uuidof(IDXGIDevice), (void **)&DXGIDevice) == S_OK) { result = (DXGIDevice->GetAdapter(DXGIAdapter) == S_OK); DXGIDevice->Release(); } } return result; }
inline void DisableDXGIWindowChanges(IUnknown* device, HWND window) { IDXGIDevice * pDXGIDevice; ThrowIfFailed(device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice))); IDXGIAdapter * pDXGIAdapter; ThrowIfFailed(pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter))); IDXGIFactory * pIDXGIFactory; ThrowIfFailed(pDXGIAdapter->GetParent(IID_PPV_ARGS(&pIDXGIFactory))); ThrowIfFailed(pIDXGIFactory->MakeWindowAssociation(window, DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER)); pIDXGIFactory->Release(); pDXGIAdapter->Release(); pDXGIDevice->Release(); }
//======================================================================== // For specified ID3D10Device returns IDXGIFactory used to create it //======================================================================== IDXGIFactory *getDeviceFactory(ID3D10Device *device) { IDXGIDevice *dxgiDevice = 0; IDXGIAdapter *dxgiAdapter = 0; IDXGIFactory *dxgiFactory = 0; if (SUCCEEDED( device->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice) )) { if (SUCCEEDED( dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&dxgiAdapter) )) { dxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&dxgiFactory); dxgiAdapter->Release(); } dxgiDevice->Release(); } return dxgiFactory; }
bool Renderer::CreateSwapChain() { // Determine buffer size RECT rect; GetClientRect(hwnd,&rect); // Create swap chain DXGI_SWAP_CHAIN_DESC SwapChainDesc; SwapChainDesc.BufferCount = 1; SwapChainDesc.BufferDesc.Width = rect.right - rect.left; SwapChainDesc.BufferDesc.Height = rect.bottom - rect.top; SwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; SwapChainDesc.BufferDesc.RefreshRate.Numerator = 60; SwapChainDesc.BufferDesc.RefreshRate.Denominator = 1; // 60/1 = 60 Hz SwapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; SwapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; SwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; SwapChainDesc.OutputWindow = hwnd; SwapChainDesc.SampleDesc.Count = 1; SwapChainDesc.SampleDesc.Quality = 0; // no AA SwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; SwapChainDesc.Windowed = true; // Obtain DXGI factory that was used to create the device // ??? IDXGIDevice* DXGIDevice; D3DDevice->QueryInterface(__uuidof(IDXGIDevice),(void**)&DXGIDevice); IDXGIAdapter* DXGIAdapter; DXGIDevice->GetParent(__uuidof(IDXGIAdapter),(void**)&DXGIAdapter); IDXGIFactory* DXGIFactory; DXGIAdapter->GetParent(__uuidof(IDXGIFactory),(void**)&DXGIFactory); // Use it if(DXGIFactory->CreateSwapChain(D3DDevice,&SwapChainDesc,&SwapChain) != S_OK) { MessageBox(hwnd,"Error creating swap chain","Error",MB_OK); return false; } // Release unused stuff DXGIDevice->Release(); DXGIAdapter->Release(); DXGIFactory->Release(); return true; }
bool DXApp::InitDirectX() { UINT createDeviceFlags = 0; #if defined(DEBUG) || defined(_DEBUG) createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; #endif D3D_FEATURE_LEVEL featurelvl; HRESULT hr = D3D11CreateDevice( 0, //default adapter D3D_DRIVER_TYPE_HARDWARE, 0, createDeviceFlags, 0, 0, D3D11_SDK_VERSION, &m_d3dDevice, &featurelvl, &m_d3dImmediateContext); if (FAILED(hr)) { MessageBox(0, L"Creation of Context failed", 0, 0); return false; } if (featurelvl != D3D_FEATURE_LEVEL_11_0) { MessageBox(0, L"DirectX11 not supported", 0, 0); return false; } m_d3dDevice->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, 4, &m_4xMsaaQuality); assert(m_4xMsaaQuality > 0); DXGI_SWAP_CHAIN_DESC sd; sd.BufferDesc.Width = m_clientWidth; sd.BufferDesc.Height = m_clientHeight; 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; if (m_enable4xMsaa) { sd.SampleDesc.Count = 4; sd.SampleDesc.Quality = m_4xMsaaQuality - 1; } else { sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = m_4xMsaaQuality - 1; } sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.BufferCount = 1; sd.OutputWindow =m_mainHandle; sd.Windowed = m_windowed; sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; sd.Flags = 0; IDXGIDevice* dxgiDevice = 0; m_d3dDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice); IDXGIAdapter* dxgiAdapter = 0; dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&dxgiAdapter); IDXGIFactory* dxgiFactory = 0; dxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&dxgiFactory); dxgiFactory->CreateSwapChain(m_d3dDevice, &sd, &m_d3dSwapChain); //NO ALT-ENTER dxgiFactory->MakeWindowAssociation(m_mainHandle, DXGI_MWA_NO_ALT_ENTER); UINT i = 0; IDXGIAdapter* pAdapter; std::vector<IDXGIAdapter*> vAdapters; while (dxgiFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND) { vAdapters.push_back(pAdapter); //pAdapter->CheckInterfaceSupport(__uuidof(DIRECT3D_VERSION), DIRECT3D_11.0); i++; } //MessageBox(0, LPCWSTR(std::to_string(vAdapters.size()).c_str()), 0, 0); for (auto a : vAdapters)a->Release(); dxgiDevice->Release(); dxgiAdapter->Release(); dxgiFactory->Release(); ID3D11Texture2D* backBuffer; m_d3dSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&backBuffer)); m_d3dDevice->CreateRenderTargetView(backBuffer, 0, &m_d3dRenderTargetView); backBuffer->Release(); D3D11_TEXTURE2D_DESC depthStencilDesc; depthStencilDesc.Width = m_clientWidth; depthStencilDesc.Height = m_clientHeight; depthStencilDesc.MipLevels = 1; depthStencilDesc.ArraySize = 1; depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; if (m_enable4xMsaa) { depthStencilDesc.SampleDesc.Count = 4; depthStencilDesc.SampleDesc.Quality = m_4xMsaaQuality - 1; } else { depthStencilDesc.SampleDesc.Count = 1; depthStencilDesc.SampleDesc.Quality = m_4xMsaaQuality - 0; } depthStencilDesc.Usage = D3D11_USAGE_DEFAULT; depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; depthStencilDesc.CPUAccessFlags = 0; depthStencilDesc.MiscFlags = 0; m_d3dDevice->CreateTexture2D(&depthStencilDesc, 0, &m_d3dDepthStencilBuffer); m_d3dDevice->CreateDepthStencilView(m_d3dDepthStencilBuffer, 0, &m_d3dDepthStencilView); m_d3dImmediateContext->OMSetRenderTargets(1, &m_d3dRenderTargetView, m_d3dDepthStencilView); D3D11_VIEWPORT vp; vp.TopLeftX = 0.f; vp.TopLeftY = 0.f; vp.Width = static_cast<float>(m_clientWidth); vp.Height = static_cast<float>(m_clientHeight); vp.MinDepth = 0.f; vp.MaxDepth = 0.f; m_d3dImmediateContext->RSSetViewports(1, &vp); return true; }
// // Initialize duplication interfaces // DUPL_RETURN DUPLICATIONMANAGER::InitDupl(_In_ ID3D11Device* Device, UINT Output) { m_OutputNumber = Output; // Take a reference on the device m_Device = Device; m_Device->AddRef(); // Get DXGI device IDXGIDevice* DxgiDevice = nullptr; HRESULT hr = m_Device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&DxgiDevice)); if (FAILED(hr)) { return ProcessFailure(nullptr, L"Failed to QI for DXGI Device", L"Error", hr); } // Get DXGI adapter IDXGIAdapter* DxgiAdapter = nullptr; hr = DxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&DxgiAdapter)); DxgiDevice->Release(); DxgiDevice = nullptr; if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to get parent DXGI Adapter", L"Error", hr, SystemTransitionsExpectedErrors); } // Get output IDXGIOutput* DxgiOutput = nullptr; hr = DxgiAdapter->EnumOutputs(Output, &DxgiOutput); DxgiAdapter->Release(); DxgiAdapter = nullptr; if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to get specified output in DUPLICATIONMANAGER", L"Error", hr, EnumOutputsExpectedErrors); } DxgiOutput->GetDesc(&m_OutputDesc); // QI for Output 1 IDXGIOutput1* DxgiOutput1 = nullptr; hr = DxgiOutput->QueryInterface(__uuidof(DxgiOutput1), reinterpret_cast<void**>(&DxgiOutput1)); DxgiOutput->Release(); DxgiOutput = nullptr; if (FAILED(hr)) { return ProcessFailure(nullptr, L"Failed to QI for DxgiOutput1 in DUPLICATIONMANAGER", L"Error", hr); } // Create desktop duplication hr = DxgiOutput1->DuplicateOutput(m_Device, &m_DeskDupl); DxgiOutput1->Release(); DxgiOutput1 = nullptr; if (FAILED(hr)) { if (hr == DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) { MessageBoxW(nullptr, L"There is already the maximum number of applications using the Desktop Duplication API running, please close one of those applications and then try again.", L"Error", MB_OK); return DUPL_RETURN_ERROR_UNEXPECTED; } return ProcessFailure(m_Device, L"Failed to get duplicate output in DUPLICATIONMANAGER", L"Error", hr, CreateDuplicationExpectedErrors); } return DUPL_RETURN_SUCCESS; }
//[-------------------------------------------------------] //[ Public methods ] //[-------------------------------------------------------] SwapChain::SwapChain(Direct3D11Renderer &direct3D11Renderer, handle nativeWindowHandle) : ISwapChain(direct3D11Renderer), mDxgiSwapChain(nullptr), mD3D11RenderTargetView(nullptr), mD3D11DepthStencilView(nullptr) { // Get the Direct3D 11 device instance ID3D11Device *d3d11Device = direct3D11Renderer.getD3D11Device(); // Get the native window handle const HWND hWnd = reinterpret_cast<HWND>(nativeWindowHandle); // Get a DXGI factory instance IDXGIFactory1 *dxgiFactory1 = nullptr; { IDXGIDevice *dxgiDevice = nullptr; IDXGIAdapter *dxgiAdapter = nullptr; d3d11Device->QueryInterface(IID_PPV_ARGS(&dxgiDevice)); dxgiDevice->GetAdapter(&dxgiAdapter); dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory1)); dxgiAdapter->Release(); dxgiDevice->Release(); } // Get the width and height of the given native window and ensure they are never ever zero // -> See "getSafeWidthAndHeight()"-method comments for details long width = 1; long height = 1; { // Get the client rectangle of the given native window RECT rect; ::GetClientRect(hWnd, &rect); // Get the width and height... width = rect.right - rect.left; height = rect.bottom - rect.top; // ... and ensure that none of them is ever zero if (width < 1) { width = 1; } if (height < 1) { height = 1; } } // Create the swap chain DXGI_SWAP_CHAIN_DESC dxgiSwapChainDesc = {}; dxgiSwapChainDesc.BufferCount = 1; dxgiSwapChainDesc.BufferDesc.Width = static_cast<UINT>(width); dxgiSwapChainDesc.BufferDesc.Height = static_cast<UINT>(height); dxgiSwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; dxgiSwapChainDesc.BufferDesc.RefreshRate.Numerator = 60; dxgiSwapChainDesc.BufferDesc.RefreshRate.Denominator = 1; dxgiSwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; dxgiSwapChainDesc.OutputWindow = hWnd; dxgiSwapChainDesc.SampleDesc.Count = 1; dxgiSwapChainDesc.SampleDesc.Quality = 0; dxgiSwapChainDesc.Windowed = TRUE; dxgiFactory1->CreateSwapChain(d3d11Device, &dxgiSwapChainDesc, &mDxgiSwapChain); // Disable alt-return for automatic fullscreen state change // -> We handle this manually to have more control over it dxgiFactory1->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER); // Release our DXGI factory dxgiFactory1->Release(); // Create the Direct3D 11 views if (nullptr != mDxgiSwapChain) { createDirect3D11Views(); } // Assign a default name to the resource for debugging purposes #ifndef DIRECT3D11RENDERER_NO_DEBUG setDebugName("Swap chain"); #endif }
//-------------------------------------------------------------------------------------- // Create Direct3D device and swap chain //-------------------------------------------------------------------------------------- HRESULT InitDevice() { HRESULT hr = S_OK; RECT rc; GetClientRect( g_hWnd, &rc ); UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top; UINT createDeviceFlags = 0; #ifdef _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, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, }; UINT numFeatureLevels = ARRAYSIZE( featureLevels ); for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ ) { g_driverType = driverTypes[driverTypeIndex]; hr = D3D11CreateDevice( nullptr, g_driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext ); if ( hr == E_INVALIDARG ) { // DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it hr = D3D11CreateDevice( nullptr, g_driverType, nullptr, createDeviceFlags, &featureLevels[1], numFeatureLevels - 1, D3D11_SDK_VERSION, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext ); } if( SUCCEEDED( hr ) ) break; } if( FAILED( hr ) ) return hr; // Obtain DXGI factory from device (since we used nullptr for pAdapter above) IDXGIFactory1* dxgiFactory = nullptr; { IDXGIDevice* dxgiDevice = nullptr; hr = g_pd3dDevice->QueryInterface( __uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice) ); if (SUCCEEDED(hr)) { IDXGIAdapter* adapter = nullptr; hr = dxgiDevice->GetAdapter(&adapter); if (SUCCEEDED(hr)) { hr = adapter->GetParent( __uuidof(IDXGIFactory1), reinterpret_cast<void**>(&dxgiFactory) ); adapter->Release(); } dxgiDevice->Release(); } } if (FAILED(hr)) return hr; // Create swap chain IDXGIFactory2* dxgiFactory2 = nullptr; hr = dxgiFactory->QueryInterface( __uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2) ); if ( dxgiFactory2 ) { // DirectX 11.1 or later hr = g_pd3dDevice->QueryInterface( __uuidof(ID3D11Device1), reinterpret_cast<void**>(&g_pd3dDevice1) ); if (SUCCEEDED(hr)) { (void) g_pImmediateContext->QueryInterface( __uuidof(ID3D11DeviceContext1), reinterpret_cast<void**>(&g_pImmediateContext1) ); } DXGI_SWAP_CHAIN_DESC1 sd; ZeroMemory(&sd, sizeof(sd)); sd.Width = width; sd.Height = height; sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.BufferCount = 1; hr = dxgiFactory2->CreateSwapChainForHwnd( g_pd3dDevice, g_hWnd, &sd, nullptr, nullptr, &g_pSwapChain1 ); if (SUCCEEDED(hr)) { hr = g_pSwapChain1->QueryInterface( __uuidof(IDXGISwapChain), reinterpret_cast<void**>(&g_pSwapChain) ); } dxgiFactory2->Release(); } else { // DirectX 11.0 systems DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof(sd)); sd.BufferCount = 1; sd.BufferDesc.Width = width; sd.BufferDesc.Height = height; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = g_hWnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; hr = dxgiFactory->CreateSwapChain( g_pd3dDevice, &sd, &g_pSwapChain ); } // Note this tutorial doesn't handle full-screen swapchains so we block the ALT+ENTER shortcut dxgiFactory->MakeWindowAssociation( g_hWnd, DXGI_MWA_NO_ALT_ENTER ); dxgiFactory->Release(); if (FAILED(hr)) return hr; // Create a render target view ID3D11Texture2D* pBackBuffer = nullptr; hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), reinterpret_cast<void**>( &pBackBuffer ) ); if( FAILED( hr ) ) return hr; hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, nullptr, &g_pRenderTargetView ); pBackBuffer->Release(); if( FAILED( hr ) ) return hr; // Create depth stencil texture D3D11_TEXTURE2D_DESC descDepth; ZeroMemory( &descDepth, sizeof(descDepth) ); descDepth.Width = width; descDepth.Height = height; descDepth.MipLevels = 1; descDepth.ArraySize = 1; descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; descDepth.SampleDesc.Count = 1; descDepth.SampleDesc.Quality = 0; descDepth.Usage = D3D11_USAGE_DEFAULT; descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL; descDepth.CPUAccessFlags = 0; descDepth.MiscFlags = 0; hr = g_pd3dDevice->CreateTexture2D( &descDepth, nullptr, &g_pDepthStencil ); if( FAILED( hr ) ) return hr; // Create the depth stencil view D3D11_DEPTH_STENCIL_VIEW_DESC descDSV; ZeroMemory( &descDSV, sizeof(descDSV) ); descDSV.Format = descDepth.Format; descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; descDSV.Texture2D.MipSlice = 0; hr = g_pd3dDevice->CreateDepthStencilView( g_pDepthStencil, &descDSV, &g_pDepthStencilView ); if( FAILED( hr ) ) return hr; g_pImmediateContext->OMSetRenderTargets( 1, &g_pRenderTargetView, g_pDepthStencilView ); // Setup the viewport D3D11_VIEWPORT vp; vp.Width = (FLOAT)width; vp.Height = (FLOAT)height; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0; vp.TopLeftY = 0; g_pImmediateContext->RSSetViewports( 1, &vp ); // Compile the vertex shader ID3DBlob* pVSBlob = nullptr; hr = CompileShaderFromFile( L"Tutorial07.fx", "VS", "vs_4_0", &pVSBlob ); if( FAILED( hr ) ) { MessageBox( nullptr, L"The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", L"Error", MB_OK ); return hr; } // Create the vertex shader hr = g_pd3dDevice->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), nullptr, &g_pVertexShader ); if( FAILED( hr ) ) { pVSBlob->Release(); return hr; } // Define the input layout D3D11_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; UINT numElements = ARRAYSIZE( layout ); // Create the input layout hr = g_pd3dDevice->CreateInputLayout( layout, numElements, pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), &g_pVertexLayout ); pVSBlob->Release(); if( FAILED( hr ) ) return hr; // Set the input layout g_pImmediateContext->IASetInputLayout( g_pVertexLayout ); // Compile the pixel shader ID3DBlob* pPSBlob = nullptr; hr = CompileShaderFromFile( L"Tutorial07.fx", "PS", "ps_4_0", &pPSBlob ); if( FAILED( hr ) ) { MessageBox( nullptr, L"The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", L"Error", MB_OK ); return hr; } // Create the pixel shader hr = g_pd3dDevice->CreatePixelShader( pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), nullptr, &g_pPixelShader ); pPSBlob->Release(); if( FAILED( hr ) ) return hr; // Create vertex buffer SimpleVertex vertices[] = { { XMFLOAT3( -1.0f, 1.0f, -1.0f ), XMFLOAT2( 1.0f, 0.0f ) }, { XMFLOAT3( 1.0f, 1.0f, -1.0f ), XMFLOAT2( 0.0f, 0.0f ) }, { XMFLOAT3( 1.0f, 1.0f, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) }, { XMFLOAT3( -1.0f, 1.0f, 1.0f ), XMFLOAT2( 1.0f, 1.0f ) }, { XMFLOAT3( -1.0f, -1.0f, -1.0f ), XMFLOAT2( 0.0f, 0.0f ) }, { XMFLOAT3( 1.0f, -1.0f, -1.0f ), XMFLOAT2( 1.0f, 0.0f ) }, { XMFLOAT3( 1.0f, -1.0f, 1.0f ), XMFLOAT2( 1.0f, 1.0f ) }, { XMFLOAT3( -1.0f, -1.0f, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) }, { XMFLOAT3( -1.0f, -1.0f, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) }, { XMFLOAT3( -1.0f, -1.0f, -1.0f ), XMFLOAT2( 1.0f, 1.0f ) }, { XMFLOAT3( -1.0f, 1.0f, -1.0f ), XMFLOAT2( 1.0f, 0.0f ) }, { XMFLOAT3( -1.0f, 1.0f, 1.0f ), XMFLOAT2( 0.0f, 0.0f ) }, { XMFLOAT3( 1.0f, -1.0f, 1.0f ), XMFLOAT2( 1.0f, 1.0f ) }, { XMFLOAT3( 1.0f, -1.0f, -1.0f ), XMFLOAT2( 0.0f, 1.0f ) }, { XMFLOAT3( 1.0f, 1.0f, -1.0f ), XMFLOAT2( 0.0f, 0.0f ) }, { XMFLOAT3( 1.0f, 1.0f, 1.0f ), XMFLOAT2( 1.0f, 0.0f ) }, { XMFLOAT3( -1.0f, -1.0f, -1.0f ), XMFLOAT2( 0.0f, 1.0f ) }, { XMFLOAT3( 1.0f, -1.0f, -1.0f ), XMFLOAT2( 1.0f, 1.0f ) }, { XMFLOAT3( 1.0f, 1.0f, -1.0f ), XMFLOAT2( 1.0f, 0.0f ) }, { XMFLOAT3( -1.0f, 1.0f, -1.0f ), XMFLOAT2( 0.0f, 0.0f ) }, { XMFLOAT3( -1.0f, -1.0f, 1.0f ), XMFLOAT2( 1.0f, 1.0f ) }, { XMFLOAT3( 1.0f, -1.0f, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) }, { XMFLOAT3( 1.0f, 1.0f, 1.0f ), XMFLOAT2( 0.0f, 0.0f ) }, { XMFLOAT3( -1.0f, 1.0f, 1.0f ), XMFLOAT2( 1.0f, 0.0f ) }, }; D3D11_BUFFER_DESC bd; ZeroMemory( &bd, sizeof(bd) ); bd.Usage = D3D11_USAGE_DEFAULT; bd.ByteWidth = sizeof( SimpleVertex ) * 24; bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = 0; D3D11_SUBRESOURCE_DATA InitData; ZeroMemory( &InitData, sizeof(InitData) ); InitData.pSysMem = vertices; hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer ); if( FAILED( hr ) ) return hr; // Set vertex buffer UINT stride = sizeof( SimpleVertex ); UINT offset = 0; g_pImmediateContext->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, &offset ); // Create index buffer // Create vertex buffer WORD indices[] = { 3,1,0, 2,1,3, 6,4,5, 7,4,6, 11,9,8, 10,9,11, 14,12,13, 15,12,14, 19,17,16, 18,17,19, 22,20,21, 23,20,22 }; bd.Usage = D3D11_USAGE_DEFAULT; bd.ByteWidth = sizeof( WORD ) * 36; bd.BindFlags = D3D11_BIND_INDEX_BUFFER; bd.CPUAccessFlags = 0; InitData.pSysMem = indices; hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pIndexBuffer ); if( FAILED( hr ) ) return hr; // Set index buffer g_pImmediateContext->IASetIndexBuffer( g_pIndexBuffer, DXGI_FORMAT_R16_UINT, 0 ); // Set primitive topology g_pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); // Create the constant buffers bd.Usage = D3D11_USAGE_DEFAULT; bd.ByteWidth = sizeof(CBNeverChanges); bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; bd.CPUAccessFlags = 0; hr = g_pd3dDevice->CreateBuffer( &bd, nullptr, &g_pCBNeverChanges ); if( FAILED( hr ) ) return hr; bd.ByteWidth = sizeof(CBChangeOnResize); hr = g_pd3dDevice->CreateBuffer( &bd, nullptr, &g_pCBChangeOnResize ); if( FAILED( hr ) ) return hr; bd.ByteWidth = sizeof(CBChangesEveryFrame); hr = g_pd3dDevice->CreateBuffer( &bd, nullptr, &g_pCBChangesEveryFrame ); if( FAILED( hr ) ) return hr; // Load the Texture hr = CreateDDSTextureFromFile( g_pd3dDevice, L"seafloor.dds", nullptr, &g_pTextureRV ); if( FAILED( hr ) ) return hr; // Create the sample state D3D11_SAMPLER_DESC sampDesc; ZeroMemory( &sampDesc, sizeof(sampDesc) ); sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; sampDesc.MinLOD = 0; sampDesc.MaxLOD = D3D11_FLOAT32_MAX; hr = g_pd3dDevice->CreateSamplerState( &sampDesc, &g_pSamplerLinear ); if( FAILED( hr ) ) return hr; // Initialize the world matrices g_World = XMMatrixIdentity(); // Initialize the view matrix XMVECTOR Eye = XMVectorSet( 0.0f, 3.0f, -6.0f, 0.0f ); XMVECTOR At = XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f ); XMVECTOR Up = XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f ); g_View = XMMatrixLookAtLH( Eye, At, Up ); CBNeverChanges cbNeverChanges; cbNeverChanges.mView = XMMatrixTranspose( g_View ); g_pImmediateContext->UpdateSubresource( g_pCBNeverChanges, 0, nullptr, &cbNeverChanges, 0, 0 ); // Initialize the projection matrix g_Projection = XMMatrixPerspectiveFovLH( XM_PIDIV4, width / (FLOAT)height, 0.01f, 100.0f ); CBChangeOnResize cbChangesOnResize; cbChangesOnResize.mProjection = XMMatrixTranspose( g_Projection ); g_pImmediateContext->UpdateSubresource( g_pCBChangeOnResize, 0, nullptr, &cbChangesOnResize, 0, 0 ); #ifdef USE_OPENVR // OpenVR. // Loading the SteamVR Runtime vr::EVRInitError eError = vr::VRInitError_None; openvr_system_ = vr::VR_Init(&eError, vr::VRApplication_Scene); if (eError != vr::VRInitError_None) { openvr_system_ = nullptr; ShowMessageBoxAndExit("Unable to init VR runtime: %s", vr::VR_GetVRInitErrorAsEnglishDescription(eError)); } if (!vr::VRCompositor()) { ShowMessageBoxAndExit("Failed to obtain compositor."); } #endif return S_OK; }
int DirectX_GraphicsDevice::Init() { HRESULT hr = S_OK; RECT rc; GetClientRect( ghMainWnd, &rc ); Width = rc.right - rc.left; Height = rc.bottom - rc.top; // Create the device and device deviceContext. unsigned int createDeviceFlags = 0; #if defined(DEBUG) || defined(_DEBUG) createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; #endif D3D_FEATURE_LEVEL featureLevel; hr = D3D11CreateDevice( 0, // use default display adapter driverType, 0, // no software device createDeviceFlags, 0, 0, // default feature level array D3D11_SDK_VERSION, &device, &featureLevel, &deviceContext); DebugPrintf("GRAPHICS: Creating Graphics Device\n"); CHECKHR(hr, "FAILED: D3D11CreateDevice not created .\n") if( featureLevel != D3D_FEATURE_LEVEL_11_0 ) { DebugPrintf("ERROR: Direct3D Feature Level 11 unsupported.\n"); MessageBox(0, L"Direct3D Feature Level 11 unsupported.", 0, 0); return 1; } hr = device->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, 4, &m4xMsaaQuality); CHECKHR(hr, "FAILED: Error Checking Multi Sample Quality Levels. \n") DebugAssert( m4xMsaaQuality > 0, "M4xMsaaQuality is 0, Multisampling with the given format and sample count combination is not supported for the installed graphics adapter."); //======= Generate Swap Chain Description ============= DXGI_SWAP_CHAIN_DESC sd; //describe backbuffer sd.BufferDesc.Width = Width; sd.BufferDesc.Height = Height; sd.BufferDesc.RefreshRate.Numerator = 1; sd.BufferDesc.RefreshRate.Denominator = 60; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; //backbuffer pixel format sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; //use backbuffer as render target sd.BufferCount = 1; //1 backbuffer, double buffering sd.OutputWindow = ghMainWnd; //give the window to render onto sd.Windowed = true; //true = windowed, false = fullscreen sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; //let the display driver select the most efficient presentation method sd.Flags = 0; sd.SampleDesc.Count = enable4xMsaa ? 4 : 1; sd.SampleDesc.Quality = enable4xMsaa ? m4xMsaaQuality-1 : 0; if(vsync_enabled) { sd.BufferDesc.RefreshRate.Numerator = 1; sd.BufferDesc.RefreshRate.Denominator = frameRateDenom; } else { sd.BufferDesc.RefreshRate.Numerator = 0; sd.BufferDesc.RefreshRate.Denominator = 1; } //====== Create the Swap Chain ======== { IDXGIDevice* dxgiDevice = 0; hr = device->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice); CHECKHR(hr, "FAILED: Could not retrieve dxgiInterface.\n") IDXGIAdapter* dxgiAdapter = 0; hr = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&dxgiAdapter); CHECKHR(hr, "FAILED: Could not retrieve dxgiAdapter.\n") IDXGIFactory* dxgiFactory = 0; hr = dxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&dxgiFactory); CHECKHR(hr, "FAILED: Could not retrieve dxgiFactory.\n") // Now, create the swap chain. hr = dxgiFactory->CreateSwapChain(device, &sd, &swapChain); CHECKHR(hr, "FAILED: Could not create SwapChain.\n") // Release our acquired COM interfaces (because we are done with them). dxgiDevice->Release(); dxgiAdapter->Release(); dxgiFactory->Release(); } if( hr = OnResize() ) { return hr; } if( hr = createTextureSampler() ) { return hr; } if( hr = createBlendStates()) { return hr; } g_Projection = g_View = g_World = DirectX::XMMatrixIdentity(); return 0; }
//-------------------------------------------------------------------------------------- // Create Direct3D device and swap chain //-------------------------------------------------------------------------------------- HRESULT InitDevice() { HRESULT hr = S_OK; RECT rc; GetClientRect( g_hWnd, &rc ); UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top; UINT createDeviceFlags = 0; #ifdef _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, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, }; UINT numFeatureLevels = ARRAYSIZE( featureLevels ); for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ ) { g_driverType = driverTypes[driverTypeIndex]; hr = D3D11CreateDevice( nullptr, g_driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext ); if ( hr == E_INVALIDARG ) { // DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it hr = D3D11CreateDevice( nullptr, g_driverType, nullptr, createDeviceFlags, &featureLevels[1], numFeatureLevels - 1, D3D11_SDK_VERSION, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext ); } if( SUCCEEDED( hr ) ) break; } if( FAILED( hr ) ) return hr; // Obtain DXGI factory from device (since we used nullptr for pAdapter above) IDXGIFactory1* dxgiFactory = nullptr; { IDXGIDevice* dxgiDevice = nullptr; hr = g_pd3dDevice->QueryInterface( __uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice) ); if (SUCCEEDED(hr)) { IDXGIAdapter* adapter = nullptr; hr = dxgiDevice->GetAdapter(&adapter); if (SUCCEEDED(hr)) { hr = adapter->GetParent( __uuidof(IDXGIFactory1), reinterpret_cast<void**>(&dxgiFactory) ); adapter->Release(); } dxgiDevice->Release(); } } if (FAILED(hr)) return hr; // Create swap chain IDXGIFactory2* dxgiFactory2 = nullptr; hr = dxgiFactory->QueryInterface( __uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2) ); if ( dxgiFactory2 ) { // DirectX 11.1 or later hr = g_pd3dDevice->QueryInterface( __uuidof(ID3D11Device1), reinterpret_cast<void**>(&g_pd3dDevice1) ); if (SUCCEEDED(hr)) { (void) g_pImmediateContext->QueryInterface( __uuidof(ID3D11DeviceContext1), reinterpret_cast<void**>(&g_pImmediateContext1) ); } DXGI_SWAP_CHAIN_DESC1 sd; ZeroMemory(&sd, sizeof(sd)); sd.Width = width; sd.Height = height; sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.BufferCount = 1; hr = dxgiFactory2->CreateSwapChainForHwnd( g_pd3dDevice, g_hWnd, &sd, nullptr, nullptr, &g_pSwapChain1 ); if (SUCCEEDED(hr)) { hr = g_pSwapChain1->QueryInterface( __uuidof(IDXGISwapChain), reinterpret_cast<void**>(&g_pSwapChain) ); } dxgiFactory2->Release(); } else { // DirectX 11.0 systems DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof(sd)); sd.BufferCount = 1; sd.BufferDesc.Width = width; sd.BufferDesc.Height = height; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = g_hWnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; hr = dxgiFactory->CreateSwapChain( g_pd3dDevice, &sd, &g_pSwapChain ); } // Note this tutorial doesn't handle full-screen swapchains so we block the ALT+ENTER shortcut dxgiFactory->MakeWindowAssociation( g_hWnd, DXGI_MWA_NO_ALT_ENTER ); dxgiFactory->Release(); if (FAILED(hr)) return hr; // Create a render target view ID3D11Texture2D* pBackBuffer = nullptr; hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), reinterpret_cast<void**>( &pBackBuffer ) ); if( FAILED( hr ) ) return hr; hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, nullptr, &g_pRenderTargetView ); pBackBuffer->Release(); if( FAILED( hr ) ) return hr; // Create depth stencil texture D3D11_TEXTURE2D_DESC descDepth; ZeroMemory( &descDepth, sizeof(descDepth) ); descDepth.Width = width; descDepth.Height = height; descDepth.MipLevels = 1; descDepth.ArraySize = 1; descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; descDepth.SampleDesc.Count = 1; descDepth.SampleDesc.Quality = 0; descDepth.Usage = D3D11_USAGE_DEFAULT; descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL; descDepth.CPUAccessFlags = 0; descDepth.MiscFlags = 0; hr = g_pd3dDevice->CreateTexture2D( &descDepth, nullptr, &g_pDepthStencil ); if( FAILED( hr ) ) return hr; // Create the depth stencil view D3D11_DEPTH_STENCIL_VIEW_DESC descDSV; ZeroMemory( &descDSV, sizeof(descDSV) ); descDSV.Format = descDepth.Format; descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; descDSV.Texture2D.MipSlice = 0; hr = g_pd3dDevice->CreateDepthStencilView( g_pDepthStencil, &descDSV, &g_pDepthStencilView ); if( FAILED( hr ) ) return hr; g_pImmediateContext->OMSetRenderTargets( 1, &g_pRenderTargetView, g_pDepthStencilView ); // Setup the viewport D3D11_VIEWPORT vp; vp.Width = (FLOAT)width; vp.Height = (FLOAT)height; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0; vp.TopLeftY = 0; g_pImmediateContext->RSSetViewports( 1, &vp ); // Compile the vertex shader ID3DBlob* pVSBlob = nullptr; hr = CompileShaderFromFile( L"Tutorial05.fx", "VS", "vs_4_0", &pVSBlob ); if( FAILED( hr ) ) { MessageBox( nullptr, L"The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", L"Error", MB_OK ); return hr; } // Create the vertex shader hr = g_pd3dDevice->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), nullptr, &g_pVertexShader ); if( FAILED( hr ) ) { pVSBlob->Release(); return hr; } // Define the input layout D3D11_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; UINT numElements = ARRAYSIZE( layout ); // Create the input layout hr = g_pd3dDevice->CreateInputLayout( layout, numElements, pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), &g_pVertexLayout ); pVSBlob->Release(); if( FAILED( hr ) ) return hr; // Set the input layout g_pImmediateContext->IASetInputLayout( g_pVertexLayout ); // Compile the pixel shader ID3DBlob* pPSBlob = nullptr; hr = CompileShaderFromFile( L"Tutorial05.fx", "PS", "ps_4_0", &pPSBlob ); if( FAILED( hr ) ) { MessageBox( nullptr, L"The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", L"Error", MB_OK ); return hr; } // Create the pixel shader hr = g_pd3dDevice->CreatePixelShader( pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), nullptr, &g_pPixelShader ); pPSBlob->Release(); if( FAILED( hr ) ) return hr; // Create vertex buffer SimpleVertex vertices[] = { { XMFLOAT3( -1.0f, 1.0f, -1.0f ), XMFLOAT4( 0.0f, 0.0f, 1.0f, 1.0f ) }, { XMFLOAT3( 1.0f, 1.0f, -1.0f ), XMFLOAT4( 0.0f, 1.0f, 0.0f, 1.0f ) }, { XMFLOAT3( 1.0f, 1.0f, 1.0f ), XMFLOAT4( 0.0f, 1.0f, 1.0f, 1.0f ) }, { XMFLOAT3( -1.0f, 1.0f, 1.0f ), XMFLOAT4( 1.0f, 0.0f, 0.0f, 1.0f ) }, { XMFLOAT3( -1.0f, -1.0f, -1.0f ), XMFLOAT4( 1.0f, 0.0f, 1.0f, 1.0f ) }, { XMFLOAT3( 1.0f, -1.0f, -1.0f ), XMFLOAT4( 1.0f, 1.0f, 0.0f, 1.0f ) }, { XMFLOAT3( 1.0f, -1.0f, 1.0f ), XMFLOAT4( 1.0f, 1.0f, 1.0f, 1.0f ) }, { XMFLOAT3( -1.0f, -1.0f, 1.0f ), XMFLOAT4( 0.0f, 0.0f, 0.0f, 1.0f ) }, }; D3D11_BUFFER_DESC bd; ZeroMemory( &bd, sizeof(bd) ); bd.Usage = D3D11_USAGE_DEFAULT; bd.ByteWidth = sizeof( SimpleVertex ) * 8; bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = 0; D3D11_SUBRESOURCE_DATA InitData; ZeroMemory( &InitData, sizeof(InitData) ); InitData.pSysMem = vertices; hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer ); if( FAILED( hr ) ) return hr; // Set vertex buffer UINT stride = sizeof( SimpleVertex ); UINT offset = 0; g_pImmediateContext->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, &offset ); // Create index buffer WORD indices[] = { 3,1,0, 2,1,3, 0,5,4, 1,5,0, 3,4,7, 0,4,3, 1,6,5, 2,6,1, 2,7,6, 3,7,2, 6,4,5, 7,4,6, }; bd.Usage = D3D11_USAGE_DEFAULT; bd.ByteWidth = sizeof( WORD ) * 36; // 36 vertices needed for 12 triangles in a triangle list bd.BindFlags = D3D11_BIND_INDEX_BUFFER; bd.CPUAccessFlags = 0; InitData.pSysMem = indices; hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pIndexBuffer ); if( FAILED( hr ) ) return hr; // Set index buffer g_pImmediateContext->IASetIndexBuffer( g_pIndexBuffer, DXGI_FORMAT_R16_UINT, 0 ); // Set primitive topology g_pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); // Create the constant buffer bd.Usage = D3D11_USAGE_DEFAULT; bd.ByteWidth = sizeof(ConstantBuffer); bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER; bd.CPUAccessFlags = 0; hr = g_pd3dDevice->CreateBuffer( &bd, nullptr, &g_pConstantBuffer ); if( FAILED( hr ) ) return hr; // Initialize the world matrix g_World1 = XMMatrixIdentity(); g_World2 = XMMatrixIdentity(); // Initialize the view matrix XMVECTOR Eye = XMVectorSet( 0.0f, 1.0f, -5.0f, 0.0f ); XMVECTOR At = XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f ); XMVECTOR Up = XMVectorSet( 0.0f, 1.0f, 0.0f, 0.0f ); g_View = XMMatrixLookAtLH( Eye, At, Up ); // Initialize the projection matrix g_Projection = XMMatrixPerspectiveFovLH( XM_PIDIV2, width / (FLOAT)height, 0.01f, 100.0f ); return S_OK; }
void DXRenderer::Resize(const UINTVECTOR2& vWinSize) { // call the parent AbstrRenderer::Resize(vWinSize); // next destroy screen dependent data we may have created already if (m_pSwapChain) OnReleasingSwapChain(); // next create the DirectX swapchain subsystem HRESULT hr = S_OK; // get the dxgi device IDXGIDevice* pDXGIDevice = NULL; hr = m_pd3dDevice->QueryInterface( IID_IDXGIDevice, ( void** )&pDXGIDevice ); if( FAILED( hr ) ) { // TODO report failiure return; } // create a swap chain DXGI_SWAP_CHAIN_DESC SwapChainDesc; ZeroMemory( &SwapChainDesc, sizeof( DXGI_SWAP_CHAIN_DESC ) ); SwapChainDesc.BufferDesc.Width = vWinSize.x; SwapChainDesc.BufferDesc.Height = vWinSize.y; SwapChainDesc.BufferDesc.RefreshRate.Numerator = 60; SwapChainDesc.BufferDesc.RefreshRate.Denominator = 1; SwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; SwapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; SwapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; SwapChainDesc.SampleDesc.Count = 1; SwapChainDesc.SampleDesc.Quality = 0; SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; SwapChainDesc.BufferCount = 3; SwapChainDesc.OutputWindow = m_hWnd; SwapChainDesc.Windowed = true; SwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; SwapChainDesc.Flags = 0; hr = m_pDXGIFactory->CreateSwapChain( pDXGIDevice, &SwapChainDesc, &m_pSwapChain ); pDXGIDevice->Release(); pDXGIDevice = NULL; if( FAILED( hr ) ) { // TODO report failiure return; } // Create a render target view ID3D10Texture2D* pBackBuffer; hr = m_pSwapChain->GetBuffer( 0, __uuidof( ID3D10Texture2D ), ( LPVOID* )&pBackBuffer ); if( FAILED( hr ) ) { // TODO report failiure return; } hr = m_pd3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &m_pRenderTargetView ); pBackBuffer->Release(); if( FAILED( hr ) ) { // TODO report failiure return; } m_pd3dDevice->OMSetRenderTargets( 1, &m_pRenderTargetView, NULL ); // Setup the viewport D3D10_VIEWPORT vp; vp.Width = vWinSize.x; vp.Height = vWinSize.y; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0; vp.TopLeftY = 0; m_pd3dDevice->RSSetViewports( 1, &vp ); // next initialize the renderer if (!OnResizedSwapChain()) { // TODO report failiure return; } }
// Direct3Dの初期化 HRESULT InitD3D( void ) { HRESULT hr = S_OK; D3D_FEATURE_LEVEL FeatureLevelsRequested[6] = { 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 }; UINT numLevelsRequested = 6; D3D_FEATURE_LEVEL FeatureLevelsSupported; // デバイス作成 hr = D3D11CreateDevice( NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, FeatureLevelsRequested, numLevelsRequested, D3D11_SDK_VERSION, &g_pd3dDevice, &FeatureLevelsSupported, &g_pImmediateContext ); if( FAILED ( hr ) ) { return hr; } // ファクトリの取得 IDXGIDevice * pDXGIDevice; hr = g_pd3dDevice->QueryInterface( __uuidof( IDXGIDevice ), ( void ** )&pDXGIDevice ); IDXGIAdapter * pDXGIAdapter; hr = pDXGIDevice->GetParent( __uuidof( IDXGIAdapter ), ( void ** )&pDXGIAdapter ); IDXGIFactory * pIDXGIFactory; pDXGIAdapter->GetParent( __uuidof( IDXGIFactory ), ( void ** )&pIDXGIFactory); // スワップチェインの作成 DXGI_SWAP_CHAIN_DESC sd; ZeroMemory( &sd, sizeof( sd ) ); sd.BufferCount = 1; sd.BufferDesc.Width = g_nClientWidth; sd.BufferDesc.Height = g_nClientHeight; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = g_hWnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; hr = pIDXGIFactory->CreateSwapChain( g_pd3dDevice, &sd, &g_pSwapChain ); pDXGIDevice->Release(); pDXGIAdapter->Release(); pIDXGIFactory->Release(); if( FAILED ( hr ) ) { return hr; } // レンダリングターゲットの生成 ID3D11Texture2D *pBackBuffer = NULL; D3D11_TEXTURE2D_DESC BackBufferSurfaceDesc; hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), ( LPVOID* )&pBackBuffer ); if ( FAILED( hr ) ) { MessageBox( NULL, _T( "Can't get backbuffer." ), _T( "Error" ), MB_OK ); return hr; } pBackBuffer->GetDesc( &BackBufferSurfaceDesc ); hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &g_pRTV ); SAFE_RELEASE( pBackBuffer ); if ( FAILED( hr ) ) { MessageBox( NULL, _T( "Can't create render target view." ), _T( "Error" ), MB_OK ); return hr; } // *** Create depth stencil texture *** D3D11_TEXTURE2D_DESC descDepth; RECT rc; GetClientRect( g_hWnd, &rc ); ZeroMemory( &descDepth, sizeof(descDepth) ); descDepth.Width = rc.right - rc.left; descDepth.Height = rc.bottom - rc.top; descDepth.MipLevels = 1; descDepth.ArraySize = 1; descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; descDepth.SampleDesc.Count = 1; descDepth.SampleDesc.Quality = 0; descDepth.Usage = D3D11_USAGE_DEFAULT; descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL; descDepth.CPUAccessFlags = 0; descDepth.MiscFlags = 0; hr = g_pd3dDevice->CreateTexture2D( &descDepth, NULL, &g_pDepthStencil ); if( FAILED( hr ) ) return hr; // *** Create the depth stencil view *** D3D11_DEPTH_STENCIL_VIEW_DESC descDSV; ZeroMemory( &descDSV, sizeof(descDSV) ); descDSV.Format = descDepth.Format; descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; descDSV.Texture2D.MipSlice = 0; hr = g_pd3dDevice->CreateDepthStencilView( g_pDepthStencil, &descDSV, &g_pDepthStencilView ); if( FAILED( hr ) ) return hr; // *** レンダリングターゲット設定 *** g_pImmediateContext->OMSetRenderTargets( 1, &g_pRTV, g_pDepthStencilView ); // ステンシルステートの作成 D3D11_DEPTH_STENCIL_DESC dsDesc; // Depth test parameters dsDesc.DepthEnable = true; dsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; dsDesc.DepthFunc = D3D11_COMPARISON_LESS; // Stencil test parameters dsDesc.StencilEnable = true; dsDesc.StencilReadMask = 0xFF; dsDesc.StencilWriteMask = 0xFF; // Stencil operations if pixel is front-facing dsDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR; dsDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; // Stencil operations if pixel is back-facing dsDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR; dsDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; // Create depth stencil state hr = g_pd3dDevice->CreateDepthStencilState( &dsDesc, &g_pDSDepthState ); dsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO; hr = g_pd3dDevice->CreateDepthStencilState( &dsDesc, &g_pDSDepthState_NoWrite ); // g_pImmediateContext->OMSetDepthStencilState( g_pDSDepthState, 1 ); // ラスタライザの設定 D3D11_RASTERIZER_DESC drd; ZeroMemory( &drd, sizeof( drd ) ); drd.FillMode = D3D11_FILL_SOLID; drd.CullMode = D3D11_CULL_NONE; drd.FrontCounterClockwise = FALSE; drd.DepthClipEnable = TRUE; hr = g_pd3dDevice->CreateRasterizerState( &drd, &g_pRS ); if ( FAILED( hr ) ) { MessageBox( NULL, _T( "Can't create rasterizer state." ), _T( "Error" ), MB_OK ); return hr; } g_pImmediateContext->RSSetState( g_pRS ); // ラスタライザの設定(時計回りカリング) ZeroMemory( &drd, sizeof( drd ) ); drd.FillMode = D3D11_FILL_SOLID; drd.CullMode = D3D11_CULL_BACK; drd.FrontCounterClockwise = TRUE; drd.DepthClipEnable = TRUE; hr = g_pd3dDevice->CreateRasterizerState( &drd, &g_pRS_Cull_CW ); if ( FAILED( hr ) ) { MessageBox( NULL, _T( "Can't create rasterizer state." ), _T( "Error" ), MB_OK ); return hr; } // g_pImmediateContext->RSSetState( g_pRS_Cull_CW ); // ラスタライザの設定(反時計回りカリング) ZeroMemory( &drd, sizeof( drd ) ); drd.FillMode = D3D11_FILL_SOLID; drd.CullMode = D3D11_CULL_BACK; drd.FrontCounterClockwise = FALSE; drd.DepthClipEnable = TRUE; hr = g_pd3dDevice->CreateRasterizerState( &drd, &g_pRS_Cull_CCW ); if ( FAILED( hr ) ) { MessageBox( NULL, _T( "Can't create rasterizer state." ), _T( "Error" ), MB_OK ); return hr; } // g_pImmediateContext->RSSetState( g_pRS_Cull_CCW ); // ビューポートの設定 D3D11_VIEWPORT vp; vp.Width = ( FLOAT )g_nClientWidth; vp.Height = ( FLOAT )g_nClientHeight; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0.0f; vp.TopLeftY = 0.0f; g_pImmediateContext->RSSetViewports( 1, &vp ); return S_OK; }
bool D3D11Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) { hWnd_ = wnd; LoadD3D11Error result = LoadD3D11(); HRESULT hr = E_FAIL; std::vector<std::string> adapterNames; std::string chosenAdapterName; if (result == LoadD3D11Error::SUCCESS) { std::vector<IDXGIAdapter *> adapters; int chosenAdapter = 0; IDXGIFactory * pFactory = nullptr; ptr_CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&pFactory); IDXGIAdapter *pAdapter; for (UINT i = 0; pFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND; i++) { adapters.push_back(pAdapter); DXGI_ADAPTER_DESC desc; pAdapter->GetDesc(&desc); std::string str = ConvertWStringToUTF8(desc.Description); adapterNames.push_back(str); if (str == g_Config.sD3D11Device) { chosenAdapter = i; } } chosenAdapterName = adapterNames[chosenAdapter]; hr = CreateTheDevice(adapters[chosenAdapter]); for (int i = 0; i < (int)adapters.size(); i++) { adapters[i]->Release(); } } if (FAILED(hr)) { const char *defaultError = "Your GPU does not appear to support Direct3D 11.\n\nWould you like to try again using Direct3D 9 instead?"; I18NCategory *err = GetI18NCategory("Error"); std::wstring error; if (result == LoadD3D11Error::FAIL_NO_COMPILER) { error = ConvertUTF8ToWString(err->T("D3D11CompilerMissing", "D3DCompiler_47.dll not found. Please install. Or press Yes to try again using Direct3D9 instead.")); } else if (result == LoadD3D11Error::FAIL_NO_D3D11) { error = ConvertUTF8ToWString(err->T("D3D11Missing", "Your operating system version does not include D3D11. Please run Windows Update.\n\nPress Yes to try again using Direct3D9 instead.")); } error = ConvertUTF8ToWString(err->T("D3D11NotSupported", defaultError)); std::wstring title = ConvertUTF8ToWString(err->T("D3D11InitializationError", "Direct3D 11 initialization error")); bool yes = IDYES == MessageBox(hWnd_, error.c_str(), title.c_str(), MB_ICONERROR | MB_YESNO); if (yes) { // Change the config to D3D9 and restart. g_Config.iGPUBackend = (int)GPUBackend::DIRECT3D9; g_Config.sFailedGPUBackends.clear(); g_Config.Save("save_d3d9_fallback"); W32Util::ExitAndRestart(); } return false; } if (FAILED(device_->QueryInterface(__uuidof (ID3D11Device1), (void **)&device1_))) { device1_ = nullptr; } if (FAILED(context_->QueryInterface(__uuidof (ID3D11DeviceContext1), (void **)&context1_))) { context1_ = nullptr; } #ifdef _DEBUG if (SUCCEEDED(device_->QueryInterface(__uuidof(ID3D11Debug), (void**)&d3dDebug_))) { if (SUCCEEDED(d3dDebug_->QueryInterface(__uuidof(ID3D11InfoQueue), (void**)&d3dInfoQueue_))) { d3dInfoQueue_->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); d3dInfoQueue_->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); d3dInfoQueue_->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_WARNING, true); } } #endif draw_ = Draw::T3DCreateD3D11Context(device_, context_, device1_, context1_, featureLevel_, hWnd_, adapterNames); SetGPUBackend(GPUBackend::DIRECT3D11, chosenAdapterName); bool success = draw_->CreatePresets(); // If we can run D3D11, there's a compiler installed. I think. _assert_msg_(G3D, success, "Failed to compile preset shaders"); int width; int height; GetRes(hWnd_, width, height); // Obtain DXGI factory from device (since we used nullptr for pAdapter above) IDXGIFactory1* dxgiFactory = nullptr; IDXGIDevice* dxgiDevice = nullptr; IDXGIAdapter* adapter = nullptr; hr = device_->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice)); if (SUCCEEDED(hr)) { hr = dxgiDevice->GetAdapter(&adapter); if (SUCCEEDED(hr)) { hr = adapter->GetParent(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&dxgiFactory)); DXGI_ADAPTER_DESC desc; adapter->GetDesc(&desc); adapter->Release(); } dxgiDevice->Release(); } // DirectX 11.0 systems DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof(sd)); sd.BufferCount = 1; sd.BufferDesc.Width = width; sd.BufferDesc.Height = height; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = hWnd_; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; hr = dxgiFactory->CreateSwapChain(device_, &sd, &swapChain_); dxgiFactory->MakeWindowAssociation(hWnd_, DXGI_MWA_NO_ALT_ENTER); dxgiFactory->Release(); GotBackbuffer(); return true; }
// Direct3Dの初期化 HRESULT InitD3D( void ) { HRESULT hr = S_OK; D3D_FEATURE_LEVEL FeatureLevelsRequested[6] = { 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 }; UINT numLevelsRequested = 6; D3D_FEATURE_LEVEL FeatureLevelsSupported; // デバイス作成 hr = D3D11CreateDevice( NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, FeatureLevelsRequested, numLevelsRequested, D3D11_SDK_VERSION, &g_pd3dDevice, &FeatureLevelsSupported, &g_pImmediateContext ); if( FAILED ( hr ) ) { return hr; } // ファクトリの取得 IDXGIDevice * pDXGIDevice; hr = g_pd3dDevice->QueryInterface( __uuidof( IDXGIDevice ), ( void ** )&pDXGIDevice ); IDXGIAdapter * pDXGIAdapter; hr = pDXGIDevice->GetParent( __uuidof( IDXGIAdapter ), ( void ** )&pDXGIAdapter ); IDXGIFactory * pIDXGIFactory; pDXGIAdapter->GetParent( __uuidof( IDXGIFactory ), ( void ** )&pIDXGIFactory); // スワップチェインの作成 DXGI_SWAP_CHAIN_DESC sd; ZeroMemory( &sd, sizeof( sd ) ); sd.BufferCount = 1; sd.BufferDesc.Width = g_nClientWidth; sd.BufferDesc.Height = g_nClientHeight; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = g_hWnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; hr = pIDXGIFactory->CreateSwapChain( g_pd3dDevice, &sd, &g_pSwapChain ); pDXGIDevice->Release(); pDXGIAdapter->Release(); pIDXGIFactory->Release(); if( FAILED ( hr ) ) { return hr; } // レンダリングターゲットの生成 ID3D11Texture2D *pBackBuffer = NULL; D3D11_TEXTURE2D_DESC BackBufferSurfaceDesc; hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), ( LPVOID* )&pBackBuffer ); if ( FAILED( hr ) ) { MessageBox( NULL, _T( "Can't get backbuffer." ), _T( "Error" ), MB_OK ); return hr; } pBackBuffer->GetDesc( &BackBufferSurfaceDesc ); hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &g_pRTV ); SAFE_RELEASE( pBackBuffer ); if ( FAILED( hr ) ) { MessageBox( NULL, _T( "Can't create render target view." ), _T( "Error" ), MB_OK ); return hr; } g_pImmediateContext->OMSetRenderTargets( 1, &g_pRTV, NULL ); // ラスタライザの設定 D3D11_RASTERIZER_DESC drd; ZeroMemory( &drd, sizeof( drd ) ); drd.FillMode = D3D11_FILL_SOLID; drd.CullMode = D3D11_CULL_NONE; drd.FrontCounterClockwise = FALSE; drd.DepthClipEnable = TRUE; hr = g_pd3dDevice->CreateRasterizerState( &drd, &g_pRS ); if ( FAILED( hr ) ) { MessageBox( NULL, _T( "Can't create rasterizer state." ), _T( "Error" ), MB_OK ); return hr; } g_pImmediateContext->RSSetState( g_pRS ); // ビューポートの設定 D3D11_VIEWPORT vp; vp.Width = ( FLOAT )g_nClientWidth; vp.Height = ( FLOAT )g_nClientHeight; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0.0f; vp.TopLeftY = 0.0f; g_pImmediateContext->RSSetViewports( 1, &vp ); return S_OK; }
bool D3DClass::Initialize(int screenWidth, int screenHeight, bool vsync, HWND hwnd, bool fullscreen, float screenDepth, float screenNear){ HRESULT hr; float fov, screenAspect; m_vsync_enabled = vsync; m_featureLevel = D3D_FEATURE_LEVEL_11_0; 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, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, }; UINT numFeatureLevels = ARRAYSIZE(featureLevels); for (int driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++){ m_driverType = driverTypes[driverTypeIndex]; hr = D3D11CreateDevice(NULL, m_driverType, NULL, 0, featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &m_device, &m_featureLevel, &m_deviceContext); if (hr == E_INVALIDARG){ hr = D3D11CreateDevice(NULL, m_driverType, NULL, 0, &featureLevels[1], numFeatureLevels - 1, D3D11_SDK_VERSION, &m_device, &m_featureLevel, &m_deviceContext); } if (SUCCEEDED(hr)){ break; } } if (FAILED(hr)){ return false; } IDXGIFactory1* factory = 0; IDXGIDevice* device = 0; hr = m_device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&device)); if (SUCCEEDED(hr)){ IDXGIAdapter* adapter = 0; hr = device->GetAdapter(&adapter); if (SUCCEEDED(hr)){ hr = adapter->GetParent(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&factory)); adapter->Release(); } device->Release(); } if (FAILED(hr)){ return false; } IDXGIFactory2* factory2 = 0; hr = factory->QueryInterface(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&factory2)); if (factory2){ hr = m_device->QueryInterface(__uuidof(ID3D11Device1), reinterpret_cast<void**>(&m_device1)); if (SUCCEEDED(hr)){ (void)m_deviceContext->QueryInterface(__uuidof(ID3D11DeviceContext1), reinterpret_cast<void**>(&m_deviceContext1)); } DXGI_SWAP_CHAIN_DESC1 sd; ZeroMemory(&sd, sizeof(sd)); sd.Width = screenWidth; sd.Height = screenHeight; sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.BufferCount = 1; hr = factory2->CreateSwapChainForHwnd(m_device, hwnd, &sd, NULL, NULL, &m_swapChain1); if (SUCCEEDED(hr)){ m_swapChain = NULL; hr = m_swapChain1->QueryInterface(__uuidof(IDXGISwapChain), reinterpret_cast<void**>(&m_swapChain)); } factory2->Release(); } else{ DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof(sd)); sd.BufferCount = 1; sd.BufferDesc.Width = screenWidth; sd.BufferDesc.Height = screenHeight; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = hwnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; hr = factory->CreateSwapChain(m_device, &sd, &m_swapChain); } factory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER); factory->Release(); if (FAILED(hr)){ return false; } ID3D11Texture2D* backBuffer = 0; hr = m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&backBuffer)); if (FAILED(hr)){ return false; } hr = m_device->CreateRenderTargetView(backBuffer, NULL, &m_renderTargetView); backBuffer->Release(); if (FAILED(hr)){ return false; } m_deviceContext->OMSetRenderTargets(1, &m_renderTargetView, NULL); D3D11_TEXTURE2D_DESC depthBufferDesc; ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc)); depthBufferDesc.Width = screenWidth; depthBufferDesc.Height = screenHeight; depthBufferDesc.MipLevels = 1; depthBufferDesc.ArraySize = 1; depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depthBufferDesc.SampleDesc.Count = 1; depthBufferDesc.SampleDesc.Quality = 0; depthBufferDesc.Usage = D3D11_USAGE_DEFAULT; depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; depthBufferDesc.CPUAccessFlags = 0; depthBufferDesc.MiscFlags = 0; hr = m_device->CreateTexture2D(&depthBufferDesc, NULL, &m_depthStencilBuffer); if (FAILED(hr)){ return false; } D3D11_DEPTH_STENCIL_DESC depthStencilDesc; ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc)); depthStencilDesc.DepthEnable = true; depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS; depthStencilDesc.StencilEnable = true; depthStencilDesc.StencilReadMask = 0xFF; depthStencilDesc.StencilWriteMask = 0xFF; depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR; depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR; depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; hr = m_device->CreateDepthStencilState(&depthStencilDesc, &m_depthStencilState); if (FAILED(hr)){ return false; } m_deviceContext->OMSetDepthStencilState(m_depthStencilState, 1); D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc; ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc)); depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; depthStencilViewDesc.Texture2D.MipSlice = 0; hr = m_device->CreateDepthStencilView(m_depthStencilBuffer, &depthStencilViewDesc, &m_depthStencilView); if (FAILED(hr)){ return false; } m_deviceContext->OMSetRenderTargets(1, &m_renderTargetView, m_depthStencilView); D3D11_RASTERIZER_DESC rasterDesc; rasterDesc.AntialiasedLineEnable = false; rasterDesc.CullMode = D3D11_CULL_BACK; rasterDesc.DepthBias = 0; rasterDesc.DepthBiasClamp = 0.0f; rasterDesc.DepthClipEnable = true; rasterDesc.FillMode = D3D11_FILL_SOLID; rasterDesc.FrontCounterClockwise = false; rasterDesc.MultisampleEnable = false; rasterDesc.ScissorEnable = false; rasterDesc.SlopeScaledDepthBias = 0.0f; hr = m_device->CreateRasterizerState(&rasterDesc, &m_rasterState); if (FAILED(hr)){ return false; } m_deviceContext->RSSetState(m_rasterState); D3D11_VIEWPORT viewport; viewport.Width = (float)screenWidth; viewport.Height = (float)screenHeight; viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; viewport.TopLeftX = 0.0f; viewport.TopLeftY = 0.0f; m_deviceContext->RSSetViewports(1, &viewport); fov = XM_PI / 4.0f; screenAspect = (float)screenWidth / (float)screenHeight; m_projectionMatrix = XMMatrixPerspectiveFovLH(fov, screenAspect, screenNear, screenDepth); m_worldMatrix = XMMatrixIdentity(); m_orthoMatrix = XMMatrixOrthographicLH((float)screenWidth, (float)screenHeight, screenNear, screenDepth); D3D11_DEPTH_STENCIL_DESC depthDisabledStencilDesc; ZeroMemory(&depthDisabledStencilDesc, sizeof(depthDisabledStencilDesc)); depthDisabledStencilDesc.DepthEnable = false; depthDisabledStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; depthDisabledStencilDesc.DepthFunc = D3D11_COMPARISON_LESS; depthDisabledStencilDesc.StencilEnable = true; depthDisabledStencilDesc.StencilReadMask = 0xFF; depthDisabledStencilDesc.StencilWriteMask = 0xFF; depthDisabledStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; depthDisabledStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR; depthDisabledStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; depthDisabledStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; depthDisabledStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; depthDisabledStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR; depthDisabledStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; depthDisabledStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; hr = m_device->CreateDepthStencilState(&depthDisabledStencilDesc, &m_depthDisabledStencilState); if (FAILED(hr)){ return false; } D3D11_BLEND_DESC blendStateDescription; ZeroMemory(&blendStateDescription, sizeof(D3D11_BLEND_DESC)); blendStateDescription.RenderTarget[0].BlendEnable = TRUE; blendStateDescription.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; blendStateDescription.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; blendStateDescription.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; blendStateDescription.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; //blendStateDescription.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_DEST_ALPHA; blendStateDescription.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; // blendStateDescription.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE; blendStateDescription.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; blendStateDescription.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; blendStateDescription.RenderTarget[0].RenderTargetWriteMask = 0x0f; hr = m_device->CreateBlendState(&blendStateDescription, &m_alphaEnableBlendingState); if (FAILED(hr)){ return false; } blendStateDescription.RenderTarget[0].BlendEnable = FALSE; hr = m_device->CreateBlendState(&blendStateDescription, &m_alphaDisableBlendingState); if (FAILED(hr)){ return false; } return true; }
BOOL IRoot::InitD3D(HWND RenderHWND, UINT BufferWidth, UINT BufferHeight, BOOL IsWindowed) { mRenderWindowHWND = RenderHWND; gMainBufferPixelWidth = BufferWidth; gMainBufferPixelHeight = BufferHeight; HRESULT hr = S_OK; #pragma region InitDevice11 //用来做判断及返回结果 //硬件驱动类型 D3D_DRIVER_TYPE driverTypes[] = { D3D_DRIVER_TYPE_HARDWARE, //HAL 硬件驱动 D3D_DRIVER_TYPE_REFERENCE, //REF参考设备 D3D_DRIVER_TYPE_WARP, //Windows Advanced Rasterization Platform只支持DX10.1 }; UINT numDriverTypes = ARRAYSIZE(driverTypes); //D3D特性的版本 D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3, }; UINT numFeatureLevels = ARRAYSIZE(featureLevels); //设备创建标签 UINT createDeviceFlags = 0; #if defined(DEBUG)||defined(_DEBUG) //D3D调试模式 createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; #endif //用列举出来的硬件方式 尝试初始化 直到成功 UINT driverTypeIndex = 0; for (driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++) { //D3D_DRIVER_TYPE g_Device_driverType = driverTypes[driverTypeIndex]; hr = D3D11CreateDevice( NULL, //null表示使用主显示器 g_Device_driverType, //驱动类型 HAL/REF NULL, D3D11_CREATE_DEVICE_DEBUG,//createDeviceFlags, //是不是调试模式 featureLevels, //让D3D选择的特性的版本 numFeatureLevels, D3D11_SDK_VERSION, &g_pd3dDevice11, //返回D3D设备指针 &g_Device_featureLevel, //返回最终使用的特性的版本 &g_pImmediateContext//返回 ); //创建成功了就不用继续尝试创建 if (SUCCEEDED(hr)) { break; }; }; //尝试创建设备失败 HR_DEBUG(hr, "d3d设备创建失败"); //检测多重采样 g_pd3dDevice11->CheckMultisampleQualityLevels( DXGI_FORMAT_R8G8B8A8_UNORM, 4, &g_Device_MSAA4xQuality);//4x坑锯齿一般都支持,这个返回值一般情况下都大于0 if (g_Device_MSAA4xQuality > 0) { g_Device_MSAA4xEnabled = TRUE; //4x抗锯齿可以开了 }; //ReleaseCOM(g_pd3dDevice11); /*填充交换链的属性 交换链,用于管理BUFEER的交换,主要处理back与front 可以用于多窗口渲染 DESC = Description*/ DXGI_SWAP_CHAIN_DESC SwapChainParam; ZeroMemory(&SwapChainParam, sizeof(SwapChainParam)); SwapChainParam.BufferCount = 1; SwapChainParam.BufferDesc.Width = gMainBufferPixelWidth; SwapChainParam.BufferDesc.Height = gMainBufferPixelHeight; SwapChainParam.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; SwapChainParam.BufferDesc.RefreshRate.Numerator = 60;// 分子= =? SwapChainParam.BufferDesc.RefreshRate.Denominator = 1;//分母 SwapChainParam.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;//BACKBUFFER怎么被使用 SwapChainParam.OutputWindow = RenderHWND; SwapChainParam.Windowed = IsWindowed; SwapChainParam.SampleDesc.Count = (g_Device_MSAA4xEnabled = TRUE ? 4 : 1);//多重采样倍数 SwapChainParam.SampleDesc.Quality = (g_Device_MSAA4xEnabled = TRUE ? g_Device_MSAA4xQuality - 1 : 0);//quality之前获取了 //下面的COM的QueryInterface 用一个接口查询另一个接口 IDXGIDevice *dxgiDevice = 0; g_pd3dDevice11->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice); IDXGIAdapter *dxgiAdapter = 0; dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&dxgiAdapter); IDXGIFactory *dxgiFactory = 0; dxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&dxgiFactory); //终于创建了一个交换链 hr = dxgiFactory->CreateSwapChain( g_pd3dDevice11, //设备的指针 &SwapChainParam, //交换链的描述 &g_pSwapChain); //返回的交换链指针 HR_DEBUG(hr, "SwapChain创建失败!"); dxgiFactory->Release(); dxgiDevice->Release(); dxgiAdapter->Release(); #pragma endregion InitDevice11 //创建缓冲区和渲染视口,深度/模版 视口 //这些Views是用来绑定到pipeline上 #pragma region CreateViews // 创建一个(可以多个)渲染视图RENDER TARGET VIEW ID3D11Texture2D* pBackBuffer = NULL; hr = g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer); if (FAILED(hr)) return FALSE; hr = g_pd3dDevice11->CreateRenderTargetView( pBackBuffer, NULL, //可以填充一个D3D11_RENDERTARGETVIEW_DESC &g_pRenderTargetView); //返回一个渲染视口 pBackBuffer->Release(); //已经用完了的临时接口- - //ReleaseCOM(g_pd3dDevice11); HR_DEBUG(hr, "创建RENDER TARGET VIEW失败"); //创建depth/stencil view D3D11_TEXTURE2D_DESC DSBufferDesc; DSBufferDesc.Width = BufferWidth; DSBufferDesc.Height = BufferHeight; DSBufferDesc.MipLevels = 1; DSBufferDesc.ArraySize = 1; DSBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; DSBufferDesc.SampleDesc.Count = (g_Device_MSAA4xEnabled = TRUE ? 4 : 1); DSBufferDesc.SampleDesc.Quality = (g_Device_MSAA4xEnabled = TRUE ? g_Device_MSAA4xQuality - 1 : 0); DSBufferDesc.Usage = D3D11_USAGE_DEFAULT; //尽量避免DYNAMIC和STAGING DSBufferDesc.CPUAccessFlags = 0; //CPU不能碰它 GPU才行 这样能够加快 DSBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;//和PIPELINE的绑定 DSBufferDesc.MiscFlags = 0; ID3D11Texture2D* pDepthStencilBuffer; g_pd3dDevice11->CreateTexture2D(&DSBufferDesc, 0, &pDepthStencilBuffer);//创建一个缓冲区 hr = g_pd3dDevice11->CreateDepthStencilView( pDepthStencilBuffer, 0, &g_pDepthStencilView); //返回一个depth/stencil视口指针 //ReleaseCOM(g_pd3dDevice11); pDepthStencilBuffer->Release(); if (FAILED(hr)) { return FALSE; }; //设置渲染对象:刚刚创建的渲染视口和depth/stencil的 //这就是绑定到pipeline g_pImmediateContext->OMSetRenderTargets( 1, &g_pRenderTargetView, g_pDepthStencilView); #pragma endregion CreateViews //XY都是-1到1,深度Z是0到1,DX11不会默认创建视口,DX9就会 #pragma region CreateViewPort D3D11_VIEWPORT vp; vp.Width = (FLOAT)BufferWidth; //视口WIDTH 跟后缓冲区一样 vp.Height = (FLOAT)BufferHeight; //视口Height vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0; vp.TopLeftY = 0; //SetViewport 参数1:视口的个数 参数2:视口数组的首地址 g_pImmediateContext->RSSetViewports(1, &vp); #pragma endregion CreateViewPort //ReleaseCOM(g_pd3dDevice11); return TRUE; };
bool CreateDevice( _Outptr_ ID3D11Device** pDevice ) { if ( !pDevice ) return false; *pDevice = nullptr; typedef HRESULT (WINAPI * LPD3D11CREATEDEVICE)( IDXGIAdapter*, D3D_DRIVER_TYPE, HMODULE, UINT32, D3D_FEATURE_LEVEL*, UINT, UINT32, ID3D11Device**, D3D_FEATURE_LEVEL*, ID3D11DeviceContext** ); static LPD3D11CREATEDEVICE s_DynamicD3D11CreateDevice = nullptr; if ( !s_DynamicD3D11CreateDevice ) { HMODULE hModD3D11 = LoadLibrary( L"d3d11.dll" ); if ( !hModD3D11 ) return false; s_DynamicD3D11CreateDevice = ( LPD3D11CREATEDEVICE )GetProcAddress( hModD3D11, "D3D11CreateDevice" ); if ( !s_DynamicD3D11CreateDevice ) return false; } D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, }; UINT createDeviceFlags = 0; #ifdef _DEBUG createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; #endif D3D_FEATURE_LEVEL fl; HRESULT hr = s_DynamicD3D11CreateDevice( nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, featureLevels, _countof(featureLevels), D3D11_SDK_VERSION, pDevice, &fl, nullptr ); if ( SUCCEEDED(hr) ) { if ( fl < D3D_FEATURE_LEVEL_11_0 ) { D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS hwopts; hr = (*pDevice)->CheckFeatureSupport( D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &hwopts, sizeof(hwopts) ); if ( FAILED(hr) ) memset( &hwopts, 0, sizeof(hwopts) ); if ( !hwopts.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x ) { if ( *pDevice ) { (*pDevice)->Release(); *pDevice = nullptr; } hr = HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); } } } if ( SUCCEEDED(hr) ) { IDXGIDevice* dxgiDevice = nullptr; hr = (*pDevice)->QueryInterface( __uuidof( IDXGIDevice ), reinterpret_cast< void** >( &dxgiDevice ) ); if ( SUCCEEDED(hr) ) { IDXGIAdapter* pAdapter = nullptr; hr = dxgiDevice->GetAdapter( &pAdapter ); if ( SUCCEEDED(hr) ) { DXGI_ADAPTER_DESC desc; hr = pAdapter->GetDesc( &desc ); if ( SUCCEEDED(hr) ) { wprintf( L"\n[Using DirectCompute on \"%s\"]\n", desc.Description ); } pAdapter->Release(); } dxgiDevice->Release(); } return true; } else return false; }
void RenderContext::Init(pWindow inWindow) { CleanUp(); HWND hWnd = inWindow->mHWnd; D3D_DRIVER_TYPE driver_type = D3D_DRIVER_TYPE_NULL; D3D_FEATURE_LEVEL feature_level = D3D_FEATURE_LEVEL_11_0; HRESULT hr = S_OK; RECT rc; GetClientRect(hWnd, &rc); mWidth = rc.right - rc.left; mHeight = rc.bottom - rc.top; UINT createDeviceFlags = 0; #ifdef _DEBUG createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; createDeviceFlags |= D3D11_CREATE_DEVICE_DISABLE_GPU_TIMEOUT; #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, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, }; UINT numFeatureLevels = ARRAYSIZE(featureLevels); for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++) { driver_type = driverTypes[driverTypeIndex]; hr = D3D11CreateDevice(nullptr, driver_type, nullptr, createDeviceFlags, featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &mD3DDevice, &feature_level, &mImmediateContext); if (hr == E_INVALIDARG) { hr = D3D11CreateDevice(nullptr, driver_type, nullptr, createDeviceFlags, &featureLevels[1], numFeatureLevels - 1, D3D11_SDK_VERSION, &mD3DDevice, &feature_level, &mImmediateContext); } if (SUCCEEDED(hr)) break; } if (FAILED(hr)) { exit(hr); } // Obtain DXGI factory from device (since we used nullptr for pAdapter above) IDXGIFactory1* dxgiFactory = nullptr; { IDXGIDevice* dxgiDevice = nullptr; hr = mD3DDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice)); if (SUCCEEDED(hr)) { IDXGIAdapter* adapter = nullptr; hr = dxgiDevice->GetAdapter(&adapter); if (SUCCEEDED(hr)) { hr = adapter->GetParent(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&dxgiFactory)); adapter->Release(); } dxgiDevice->Release(); } } if (FAILED(hr)) { exit(hr); } // Create swap chain IDXGIFactory2* dxgiFactory2 = nullptr; hr = dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2)); if (dxgiFactory2) { // DirectX 11.1 or later hr = mD3DDevice->QueryInterface(__uuidof(ID3D11Device1), reinterpret_cast<void**>(&mD3DDevice1)); if (SUCCEEDED(hr)) { (void)mImmediateContext->QueryInterface(__uuidof(ID3D11DeviceContext1), reinterpret_cast<void**>(&mImmediateContext1)); } DXGI_SWAP_CHAIN_DESC1 sd; ZeroMemory(&sd, sizeof(sd)); sd.Width = mWidth; sd.Height = mHeight; sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_UNORDERED_ACCESS; sd.BufferCount = 1; hr = dxgiFactory2->CreateSwapChainForHwnd(mD3DDevice, hWnd, &sd, nullptr, nullptr, &mSwapChain1); if (SUCCEEDED(hr)) { hr = mSwapChain1->QueryInterface(__uuidof(IDXGISwapChain), reinterpret_cast<void**>(&mSwapChain)); } dxgiFactory2->Release(); } else { // DirectX 11.0 systems DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof(sd)); sd.BufferCount = 1; sd.BufferDesc.Width = mWidth; sd.BufferDesc.Height = mHeight; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_UNORDERED_ACCESS; sd.OutputWindow = hWnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; hr = dxgiFactory->CreateSwapChain(mD3DDevice, &sd, &mSwapChain); } // Note this tutorial doesn't handle full-screen swapchains so we block the ALT+ENTER shortcut dxgiFactory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER); dxgiFactory->Release(); if (FAILED(hr)) { exit(hr); } // Create a render target view ID3D11Texture2D* pBackBuffer = nullptr; hr = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&pBackBuffer)); if (FAILED(hr)) { exit(hr); } mBackBuffer = MAKE_NEW(Texture); mBackBuffer->Init(pBackBuffer); mOutputRenderTarget = MAKE_NEW(RenderTarget); mOutputRenderTarget->Init(mBackBuffer); // setup rasterizer SetRasterizerState(FILL_SOLID, CULL_BACK, true, 0, 0.0f, 0.0f, true, false, false, false); D3D11_DEPTH_STENCIL_DESC dsDesc; dsDesc.DepthEnable = true; dsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; dsDesc.DepthFunc = D3D11_COMPARISON_LESS; dsDesc.StencilEnable = false; dsDesc.StencilReadMask = 0xFF; dsDesc.StencilWriteMask = 0xFF; dsDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR; dsDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; // Stencil operations if pixel is back-facing dsDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR; dsDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; // Create depth stencil state ID3D11DepthStencilState * pDSState; mD3DDevice->CreateDepthStencilState(&dsDesc, &pDSState); mImmediateContext->OMSetDepthStencilState(pDSState, 1); // Setup the viewport SetViewport(int2(mWidth, mHeight), 0.0f, 1.0f, int2(0, 0)); hr = mImmediateContext->QueryInterface(__uuidof(mAnnotation), reinterpret_cast<void**>(&mAnnotation)); if (FAILED(hr)) { exit(hr); } mInitialized = true; }
//-------------------------------------------------------------------------------------- // Create Direct3D device and swap chain //-------------------------------------------------------------------------------------- HRESULT InitDevice() { HRESULT hr = S_OK; RECT rc; GetClientRect( g_hWnd, &rc ); UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top; UINT createDeviceFlags = 0; #ifdef _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, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, }; UINT numFeatureLevels = ARRAYSIZE( featureLevels ); for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ ) { g_driverType = driverTypes[driverTypeIndex]; hr = D3D11CreateDevice( nullptr, g_driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext ); if ( hr == E_INVALIDARG ) { // DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it hr = D3D11CreateDevice( nullptr, g_driverType, nullptr, createDeviceFlags, &featureLevels[1], numFeatureLevels - 1, D3D11_SDK_VERSION, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext ); } if( SUCCEEDED( hr ) ) break; } if( FAILED( hr ) ) return hr; // Obtain DXGI factory from device (since we used nullptr for pAdapter above) IDXGIFactory1* dxgiFactory = nullptr; { IDXGIDevice* dxgiDevice = nullptr; hr = g_pd3dDevice->QueryInterface( __uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice) ); if (SUCCEEDED(hr)) { IDXGIAdapter* adapter = nullptr; hr = dxgiDevice->GetAdapter(&adapter); if (SUCCEEDED(hr)) { hr = adapter->GetParent( __uuidof(IDXGIFactory1), reinterpret_cast<void**>(&dxgiFactory) ); adapter->Release(); } dxgiDevice->Release(); } } if (FAILED(hr)) return hr; // Create swap chain IDXGIFactory2* dxgiFactory2 = nullptr; hr = dxgiFactory->QueryInterface( __uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2) ); if ( dxgiFactory2 ) { // DirectX 11.1 or later hr = g_pd3dDevice->QueryInterface( __uuidof(ID3D11Device1), reinterpret_cast<void**>(&g_pd3dDevice1) ); if (SUCCEEDED(hr)) { (void) g_pImmediateContext->QueryInterface( __uuidof(ID3D11DeviceContext1), reinterpret_cast<void**>(&g_pImmediateContext1) ); } DXGI_SWAP_CHAIN_DESC1 sd = {}; sd.Width = width; sd.Height = height; sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.BufferCount = 1; hr = dxgiFactory2->CreateSwapChainForHwnd( g_pd3dDevice, g_hWnd, &sd, nullptr, nullptr, &g_pSwapChain1 ); if (SUCCEEDED(hr)) { hr = g_pSwapChain1->QueryInterface( __uuidof(IDXGISwapChain), reinterpret_cast<void**>(&g_pSwapChain) ); } dxgiFactory2->Release(); } else { // DirectX 11.0 systems DXGI_SWAP_CHAIN_DESC sd = {}; sd.BufferCount = 1; sd.BufferDesc.Width = width; sd.BufferDesc.Height = height; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = g_hWnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; hr = dxgiFactory->CreateSwapChain( g_pd3dDevice, &sd, &g_pSwapChain ); } // Note this tutorial doesn't handle full-screen swapchains so we block the ALT+ENTER shortcut dxgiFactory->MakeWindowAssociation( g_hWnd, DXGI_MWA_NO_ALT_ENTER ); dxgiFactory->Release(); if (FAILED(hr)) return hr; // Create a render target view ID3D11Texture2D* pBackBuffer = nullptr; hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), reinterpret_cast<void**>( &pBackBuffer ) ); if( FAILED( hr ) ) return hr; hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, nullptr, &g_pRenderTargetView ); pBackBuffer->Release(); if( FAILED( hr ) ) return hr; g_pImmediateContext->OMSetRenderTargets( 1, &g_pRenderTargetView, nullptr ); // Setup the viewport D3D11_VIEWPORT vp; vp.Width = (FLOAT)width; vp.Height = (FLOAT)height; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0; vp.TopLeftY = 0; g_pImmediateContext->RSSetViewports( 1, &vp ); return S_OK; }
bool Renderer::Init() { UINT createDeviceFlags = 0; #if defined(DEBUG) || defined(_DEBUG) //createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; //createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUGGABLE; #endif D3D_FEATURE_LEVEL featureLevel; HRESULT hresult = D3D11CreateDevice(0, _d3dDriverType, 0, createDeviceFlags, 0, 0, D3D11_SDK_VERSION, &_d3dDevice, &featureLevel, &_d3dImmediateContext); if (FAILED(hresult)) { // TODO: Throw exceptions _logger.LogLine(L"Failed to initialize Renderer: Failed to create D3D11CreateDevice."); _logger.LogHResult(hresult); MessageBox(0, L"Failed to initialize Renderer, see log for details.", 0, 0); return false; } if (featureLevel != D3D_FEATURE_LEVEL_11_0) //if (featureLevel != 0xc000) { // TODO: Throw exceptions _logger.LogLine(L"Failed to initialize Renderer: Required D3D feature level 11 not supported."); MessageBox(0, L"Failed to initialize Renderer, see log for details.", 0, 0); return false; } hresult = (_d3dDevice->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, 4, &_4xMsaaQuality)); if (FAILED(hresult)) { _logger.LogHResult(hresult); } assert(_4xMsaaQuality > 0); DXGI_SWAP_CHAIN_DESC swapChainDescription; swapChainDescription.BufferDesc.Width = _clientWidth; swapChainDescription.BufferDesc.Height = _clientHeight; swapChainDescription.BufferDesc.RefreshRate.Numerator = 60; swapChainDescription.BufferDesc.RefreshRate.Denominator = 1; swapChainDescription.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; swapChainDescription.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; swapChainDescription.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; if (_enable4xMsaa) { swapChainDescription.SampleDesc.Count = 4; swapChainDescription.SampleDesc.Quality = _4xMsaaQuality - 1; } else { swapChainDescription.SampleDesc.Count = 1; swapChainDescription.SampleDesc.Quality = 0; } swapChainDescription.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDescription.BufferCount = 1; swapChainDescription.OutputWindow = _windowHandle; swapChainDescription.Windowed = true; swapChainDescription.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; swapChainDescription.Flags = 0; IDXGIDevice* dxgiDevice = 0; hresult = (_d3dDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice)); if (FAILED(hresult)) { _logger.LogHResult(hresult); } IDXGIAdapter* dxgiAdapter = 0; hresult = (dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&dxgiAdapter)); if (FAILED(hresult)) { _logger.LogHResult(hresult); } IDXGIFactory* dxgiFactory = 0; hresult = (dxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&dxgiFactory)); if (FAILED(hresult)) { _logger.LogHResult(hresult); } hresult = (dxgiFactory->CreateSwapChain(_d3dDevice, &swapChainDescription, &_swapChain)); if (FAILED(hresult)) { _logger.LogHResult(hresult); } if (dxgiDevice) { dxgiDevice->Release(); dxgiDevice = 0; } if (dxgiAdapter) { dxgiAdapter->Release(); dxgiAdapter = 0; } if (dxgiFactory) { dxgiFactory->Release(); dxgiFactory = 0; } OnResize(); return true; }
//-------------------------------------------------------------------------------------- // Render a frame //-------------------------------------------------------------------------------------- void Render() { // Clear the back buffer //float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; // red,green,blue,alpha //make sure the texture changes the whole time g_ClearColor[0] = ( g_ClearColor[0] + 0.0010f ); if (g_ClearColor[0] >= 1) g_ClearColor[0] -= 1.0f; g_ClearColor[1] = ( g_ClearColor[1] + 0.0009f ); if (g_ClearColor[1] >= 1) g_ClearColor[1] -= 1.0f; g_ClearColor[2] = ( g_ClearColor[2] + 0.0008f ); if (g_ClearColor[2] >= 1) g_ClearColor[2] -= 1.0f; /////////////////////////////////////////////////////////////////////////////////////////// //// COPY THE BACKBUFFER TO OUR (global) SHARED TEXTURE /////////////////////////////////////////////////////////////////////////////////////////// ID3D11Texture2D* pSourceBuffer; //will be used to copy the backbuffer to our sharedTexture ////g_pImmediateContext-> ////g_pSwapChain-> g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pSourceBuffer); //if ( g_pSharedTexture == NULL && pSourceBuffer != NULL ) { // //IDirect3D9Ex_CreateDevice(p,a, b ,c,d,e,f); // D3D11_TEXTURE2D_DESC td; pSourceBuffer->GetDesc(&td); //make it a shared texture, so add a flag td.MiscFlags |= D3D11_RESOURCE_MISC_SHARED; td.MipLevels = 1; td.Usage = D3D11_USAGE_DEFAULT; td.ArraySize = 1; td.BindFlags = 0; //D3D11_BIND_RENDER_TARGET; td.Format = DXGI_FORMAT_B8G8R8A8_UNORM; //DXGI_FORMAT_R8G8B8A8_UNORM; //CD3D11_TEXTURE2D_DESC td2 = new CD3D11_TEXTURE2D_DESC(...); // I think we should create a D3D9ex shared texture and share that. Using the same handle we should open our D3D11 copy ourselves... // Some hints here http://xboxforums.create.msdn.com/forums/t/103939.aspx if (g_pSharedTexture == NULL) { //Ideally end up with 1 simple function somewhat like this: CreateD3D10SharedTexture(pSourceBuffer, g_pd3dDevice, &g_pSharedTexture); #define USE_DLL true #define USE_FUNCTION true //only relevant if USE_DLL = false HANDLE d3d9exShareHandle = NULL; PDIRECT3DTEXTURE9 pD3D9Texture = NULL; D3DFORMAT format = D3DFMT_A32B32G32R32F; //D3DFMT_A8R8G8B8; //D3DFMT_X8R8G8B8; if ( USE_DLL ) { PDIRECT3DTEXTURE9 pD3D9Texture = NULL; //unsigned __int32 sharedTextureHandleInt; HRESULT hr = CreateDX9ExTexture( td.Width, td.Height, D3DUSAGE_RENDERTARGET, format, &pD3D9Texture, &d3d9exShareHandle ); //d3d9exShareHandle = (HANDLE)sharedTextureHandleInt; } else if ( ! USE_FUNCTION ) { IDirect3D9Ex * pDirect3D9Ex; IDirect3DDevice9 * pDeviceD3D9; IDirect3DDevice9Ex * pDeviceD3D9ex; ID3D10Device1 * pDeviceD3D10_1; //Get adapter of the current D3D11 device. Our D3D10 will run on the same adapter. IDXGIDevice* pDXGIDevice; IDXGIAdapter* pAdapter; g_pd3dDevice->QueryInterface<IDXGIDevice>(&pDXGIDevice); //g_pd3dDevice->QueryInterface<IDirect3DDevice9Ex>(&pDeviceD3D9ex); pDXGIDevice->GetAdapter(&pAdapter); pDXGIDevice->Release(); //////// If we add the lib-file to the linker there is no need to load this dll dynamically /////////////////////////////////////////////////////////////////////////////////////////// ////Get address of the function D3D10CreateDevice1 dynamically. ////Load D3D10.DLL ////HMODULE m_hD3D9 = LoadLibrary(L"d3d9.dll"); //HMODULE m_hD3D10 = LoadLibrary(L"d3d10_1.dll"); //typedef HRESULT (WINAPI* FN_D3D10CreateDevice1)(IDXGIAdapter *pAdapter, D3D10_DRIVER_TYPE DriverType, HMODULE Software, // UINT Flags, D3D10_FEATURE_LEVEL1 HardwareLevel, UINT SDKVersion, ID3D10Device1 **ppDevice ); //FN_D3D10CreateDevice1 fnCreate = (FN_D3D10CreateDevice1)GetProcAddress(m_hD3D10, "D3D10CreateDevice1"); ////Call D3D10CreateDevice1 dynamically. //fnCreate( pAdapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, D3D10_CREATE_DEVICE_BGRA_SUPPORT | D3D10_CREATE_DEVICE_DEBUG, // D3D10_FEATURE_LEVEL_10_1, D3D10_1_SDK_VERSION, &pDeviceD3D10_1); D3D10CreateDevice1(pAdapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, D3D10_CREATE_DEVICE_BGRA_SUPPORT | D3D10_CREATE_DEVICE_DEBUG, D3D10_FEATURE_LEVEL_10_1, D3D10_1_SDK_VERSION, &pDeviceD3D10_1); //Now we have a D3D10 device: m_pInterD3D10 (which means the Intermediate Direct3D10 device). //Now let’s share it with D3D11. Do this on your Swapchain Resizing event. (Because size of the Render Target changes): D3DPRESENT_PARAMETERS present_parameters = {0}; //IDirect3DDevice9Ex *device; //D3DDISPLAYMODEEX mode; //, *m; // WE DON'T NEED A SEPARATE WINDOW TO CREATE OUR D3D9ex device !!! ////////////////////////////////////////////////////////////////// // Create window //RECT rc = { 0, 0, 640, 480 }; //AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE ); //if (g_hWnd_D3D9Ex == NULL) { // g_hWnd_D3D9Ex = CreateWindow( L"TutorialWindowClass", L"D3D9Ex window - Direct3D 11 Tutorial 2: Rendering a Triangle", // WS_OVERLAPPEDWINDOW, // CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, g_hInst, // NULL ); // ShowWindow( g_hWnd_D3D9Ex, SW_SHOWNA ); //} ZeroMemory( &present_parameters, sizeof(present_parameters) ); present_parameters.Windowed = true; present_parameters.hDeviceWindow = NULL; //g_hWnd; //g_hWnd_D3D9Ex; present_parameters.SwapEffect = D3DSWAPEFFECT_COPY; present_parameters.BackBufferWidth = td.Width; present_parameters.BackBufferHeight = td.Height; present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8; present_parameters.EnableAutoDepthStencil = FALSE; present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8; present_parameters.BackBufferCount = 1; //present_parameters.Flags = 0; //present_parameters.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; //mode.Size = sizeof(mode); //mode.Width = td.Width; //mode.Height = td.Height; //mode.RefreshRate = 0; //mode.Format = D3DFMT_A8R8G8B8; //mode.ScanLineOrdering = D3DSCANLINEORDERING_UNKNOWN; ////Create a D3D10.1 render target texture and share it with our D3D11. //D3D10_TEXTURE2D_DESC tDesc; //tDesc.Width = td.Width; //tDesc.Height = td.Height; //tDesc.MipLevels = 1; //tDesc.ArraySize = 1; //tDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; //DXGI_FORMAT_R8G8B8A8_UNORM; //tDesc.SampleDesc.Count = 1; //tDesc.SampleDesc.Quality = 0; //tDesc.Usage = D3D10_USAGE_DEFAULT; ////EVEN IF YOU WON'T USE AS SHADER RESOURCE, SET THIS BIND FLAGS: //tDesc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE; //tDesc.CPUAccessFlags = 0; //tDesc.MiscFlags = D3D10_RESOURCE_MISC_SHARED;// Direct3DCreate9Ex( D3D_SDK_VERSION, //_Out_ &pDirect3D9Ex); HRESULT hr; //This works D3DDISPLAYMODE d3ddm = {0}; pDirect3D9Ex->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ); //This doesn't work D3DDISPLAYMODEEX d3ddmex; d3ddmex.Size = sizeof(d3ddmex); d3ddmex.Width = d3ddm.Width; d3ddmex.Height = d3ddm.Height; d3ddmex.Format = d3ddm.Format; d3ddmex.ScanLineOrdering = D3DSCANLINEORDERING_UNKNOWN; //D3DDISPLAYROTATION d3ddrot; //if( S_OK != ( hr = pDirect3D9Ex->GetAdapterDisplayModeEx( D3DADAPTER_DEFAULT, &d3ddmex, &d3ddrot ) ) ) //{ // // TO DO: Respond to failure of GetAdapterDisplayMode // return; //} if ( S_OK != ( hr = pDirect3D9Ex->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3ddm.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16 ) ) ) { if( hr == D3DERR_NOTAVAILABLE ) // POTENTIAL PROBLEM: We need at least a 16-bit z-buffer! return; } // Do we support hardware vertex processing? if so, use it. // If not, downgrade to software. D3DCAPS9 d3dCaps; if( S_OK != pDirect3D9Ex->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps ) ) { // TO DO: Respond to failure of GetDeviceCaps return; } DWORD dwBehaviorFlags = 0; if( d3dCaps.VertexProcessingCaps != 0 ) dwBehaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING; else dwBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING; DWORD d3d9ex_usage = D3DUSAGE_RENDERTARGET | D3DUSAGE_NONSECURE | (dwBehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING ? 0 : D3DUSAGE_SOFTWAREPROCESSING); //HRESULT createDeviceHR = pDirect3D9Ex->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd_D3D9Ex, dwBehaviorFlags, &present_parameters, &pDeviceD3D9); //if (createDeviceHR == S_OK) { // hr = pDeviceD3D9->CreateTexture(td.Width, td.Height, 1 // , D3DUSAGE_RENDERTARGET //| D3DUSAGE_SOFTWAREPROCESSING // , D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pD3D9Texture, &d3d9exShareHandle); // if ( pD3D9Texture == NULL ) { // Sleep(1000); // } //} //else if (D3DERR_DEVICELOST == createDeviceHR) // Sleep(1000); //else if (D3DERR_INVALIDCALL == createDeviceHR) // Sleep(1000); //else if (D3DERR_WRONGTEXTUREFORMAT == createDeviceHR) // Sleep(1000); HRESULT createDeviceExHR = pDirect3D9Ex->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd_D3D9Ex, dwBehaviorFlags, &present_parameters, NULL, &pDeviceD3D9ex); if (createDeviceExHR == S_OK) { hr = pDeviceD3D9ex->CreateTexture(td.Width, td.Height, 1, d3d9ex_usage, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pD3D9Texture, &d3d9exShareHandle); } else if (D3DERR_DEVICELOST == createDeviceExHR) Sleep(1000); else if (D3DERR_INVALIDCALL == createDeviceExHR) Sleep(1000); else if (D3DERR_WRONGTEXTUREFORMAT == createDeviceExHR) Sleep(1000); ////Create the RT texture on D3D10 //ID3D10Texture2D * pD3D10Texture; //pDeviceD3D10_1->CreateTexture2D( &tDesc, NULL, &pD3D10Texture); ////Get DXGI Resource and retrieve the sharing handle. //IDXGISurface * pDXGISurf; //IDXGIResource * pDXGIRes; //HANDLE d3d10ShareHandle; //pD3D10Texture->QueryInterface<IDXGISurface>(&pDXGISurf); //pDXGISurf->QueryInterface<IDXGIResource>(&pDXGIRes); //pDXGIRes->GetSharedHandle( &d3d9exShareHandle ); //pDXGIRes->Release(); //pDXGISurf->Release(); } else { //IF USE_FUNCTION //DWORD usage = D3DUSAGE_RENDERTARGET; PDIRECT3DTEXTURE9 pD3D9Texture = NULL; HRESULT hr = MyCreateDX9ExTexture(td.Width, td.Height, format /*D3DFMT_A8R8G8B8*/, D3DUSAGE_RENDERTARGET, &pD3D9Texture, &d3d9exShareHandle); } if (d3d9exShareHandle != NULL) { ////Call D3D 11 to open shared resource (m_pDevice is the D3D11 device). ID3D11Resource * pD3D11Res; //ID3D11Texture2D * m_pInterRTD3D11; g_pd3dDevice->OpenSharedResource(d3d9exShareHandle, __uuidof(ID3D11Resource), (void**)&pD3D11Res); pD3D11Res->QueryInterface<ID3D11Texture2D>(&g_pSharedTexture); pD3D11Res->Release(); g_pImmediateContext->CopyResource(g_pSharedTexture, pSourceBuffer); ShareD3DTexture(g_hWyphonPartner, d3d9exShareHandle, td.Width, td.Height, format, D3DUSAGE_RENDERTARGET, TEXT("screen output")); //SimpleVertex vertices[] = //{ // { XMFLOAT3( -1.0f, 1.0f, -1.0f ), XMFLOAT2( 1.0f, 0.0f ) }, // { XMFLOAT3( 1.0f, 1.0f, -1.0f ), XMFLOAT2( 0.0f, 0.0f ) }, // { XMFLOAT3( 1.0f, 1.0f, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) }, // { XMFLOAT3( -1.0f, 1.0f, 1.0f ), XMFLOAT2( 1.0f, 1.0f ) }, //}; } else { Sleep(1000); } } //if ( g_pSharedTexture == NULL ) { //Render to SCREEN g_pImmediateContext->OMSetRenderTargets( 1, &g_pRenderTargetView, NULL ); g_pImmediateContext->ClearRenderTargetView( g_pRenderTargetView, g_ClearColor ); // Render a triangle g_pImmediateContext->VSSetShader( g_pVertexShader, NULL, 0 ); g_pImmediateContext->PSSetShader( g_pPixelShader, NULL, 0 ); g_pImmediateContext->Draw( 3, 0 ); // Present the information rendered to the back buffer to the front buffer (the screen) g_pSwapChain->Present( 0, 0 ); //} if ( g_pSharedTexture != NULL ) { //Render to TEXTURE // If screen and shared texture have the same format, we could CopyResource the backbuffer to the texture ///////////////////////////////////////////////////////////////////////////////////////////////////////// //g_pImmediateContext->CopyResource(g_pSharedTexture, pSourceBuffer); // Otherwise, we need to setup the texture as the rendertarget, and render the scene again ////////////////////////////////////////////////////////////////////////////////////////// //g_pImmediateContext->Flush(); HRESULT result; D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc; D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc; ID3D11RenderTargetView* m_renderTargetView = NULL; ID3D11ShaderResourceView* m_shaderResourceView = NULL; // Setup the description of the render target view. D3D11_TEXTURE2D_DESC textureDesc; g_pSharedTexture->GetDesc(&textureDesc); renderTargetViewDesc.Format = textureDesc.Format; renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; renderTargetViewDesc.Texture2D.MipSlice = 0; // Create the render target view. result = g_pd3dDevice->CreateRenderTargetView(g_pSharedTexture, &renderTargetViewDesc, &m_renderTargetView); if(FAILED(result)) { } else { // Setup the description of the shader resource view. shaderResourceViewDesc.Format = textureDesc.Format; shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; shaderResourceViewDesc.Texture2D.MostDetailedMip = 0; shaderResourceViewDesc.Texture2D.MipLevels = 1; // Create the shader resource view. //result = g_pd3dDevice->CreateShaderResourceView(g_pSharedTexture, &shaderResourceViewDesc, &m_shaderResourceView); //if(FAILED(result)) //{ //} //else { //ID3D11DepthStencilView* m_depthStencilView; g_pImmediateContext->OMSetRenderTargets( 1, &m_renderTargetView, NULL ); g_pImmediateContext->ClearRenderTargetView( m_renderTargetView, g_ClearColor ); // Render a triangle g_pImmediateContext->VSSetShader( g_pVertexShader, NULL, 0 ); g_pImmediateContext->PSSetShader( g_pPixelShader, NULL, 0 ); g_pImmediateContext->Draw( 3, 0 ); //g_pImmediateContext->Flush(); // Present the information rendered to the back buffer to the front buffer (the screen) //g_pSwapChain->Present( 0, 0 ); //cleanup if ( m_shaderResourceView != NULL ) m_shaderResourceView->Release(); if ( m_renderTargetView != NULL ) m_renderTargetView->Release(); //} } /* Something similar in D3D9Ex //set new render target g_pd3dDevice->SetRenderTarget(0,pRenderSurface); //clear texture g_App.GetDevice()->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(100,100,100), 1.0f, 0); g_App.GetDevice()->BeginScene(); g_App.GetDevice()->SetTexture(0,pPyramideTexture); D3DXMatrixRotationY(&matRotationY,fRotation); D3DXMatrixTranslation(&matTranslation,0.0f,0.0f,5.0f); g_App.GetDevice()->SetTransform(D3DTS_WORLD, &(matRotationY * matTranslation)); //set projection matrix g_App.GetDevice()->SetTransform(D3DTS_PROJECTION,&matProjection); g_App.GetDevice()->SetStreamSource(0,pTriangleVB,0,sizeof(D3DVERTEX)); g_App.GetDevice()->DrawPrimitive(D3DPT_TRIANGLELIST,0,4); g_App.GetDevice()->EndScene(); */ } Sleep(10); // ID3D11Texture2D* pSurface; // HRESULT hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), reinterpret_cast< void** >( &pSurface ) ); // if( pSurface ) // { // //ft: added m_dpi myself // int m_dpi = 96; // // const int width = static_cast<int>(m_window->Bounds.Width * m_dpi / 96.0f); // const int height = static_cast<int>(m_window->Bounds.Height * m_dpi / 96.0f); // unsigned int size = width * height; // if( m_captureData ) // { // freeFramebufferData( m_captureData ); // } // m_captureData = new unsigned char[ width * height * 4 ]; // // ID3D11Texture2D* pNewTexture = NULL; // // D3D11_TEXTURE2D_DESC description; // pSurface->GetDesc( &description ); // description.BindFlags = 0; // description.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; // description.Usage = D3D11_USAGE_STAGING; // // HRESULT hr = m_d3dDevice->CreateTexture2D( &description, NULL, &pNewTexture ); // if ( pNewTexture ) // { // m_d3dContext->CopyResource( pNewTexture, pSurface ); // D3D11_MAPPED_SUBRESOURCE resource; // unsigned int subresource = D3D11CalcSubresource( 0, 0, 0 ); // HRESULT hr = m_d3dContext->Map( pNewTexture, subresource, D3D11_MAP_READ_WRITE, 0, &resource ); // //resource.pData; // TEXTURE DATA IS HERE // // const int pitch = width << 2; // const unsigned char* source = static_cast< const unsigned char* >( resource.pData ); // unsigned char* dest = m_captureData; // for( int i = 0; i < height; ++i ) // { // memcpy( dest, source, width * 4 ); // source += pitch; // dest += pitch; // } // // m_captureSize = size; // m_captureWidth = width; // m_captureHeight = height; // // return; // } // // freeFramebufferData( m_captureData ); // } }
// // Recreate shared texture // DUPL_RETURN OUTPUTMANAGER::CreateSharedSurf(INT SingleOutput, _Out_ UINT* OutCount, _Out_ RECT* DeskBounds) { HRESULT hr; // Get DXGI resources IDXGIDevice* DxgiDevice = nullptr; hr = m_Device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&DxgiDevice)); if (FAILED(hr)) { return ProcessFailure(nullptr, L"Failed to QI for DXGI Device", L"Error", hr); } IDXGIAdapter* DxgiAdapter = nullptr; hr = DxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&DxgiAdapter)); DxgiDevice->Release(); DxgiDevice = nullptr; if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to get parent DXGI Adapter", L"Error", hr, SystemTransitionsExpectedErrors); } // Set initial values so that we always catch the right coordinates DeskBounds->left = INT_MAX; DeskBounds->right = INT_MIN; DeskBounds->top = INT_MAX; DeskBounds->bottom = INT_MIN; IDXGIOutput* DxgiOutput = nullptr; // Figure out right dimensions for full size desktop texture and # of outputs to duplicate UINT OutputCount; if (SingleOutput < 0) { hr = S_OK; for (OutputCount = 0; SUCCEEDED(hr); ++OutputCount) // for (OutputCount = 0; OutputCount<1; ++OutputCount) { if (DxgiOutput) { DxgiOutput->Release(); DxgiOutput = nullptr; } hr = DxgiAdapter->EnumOutputs(OutputCount, &DxgiOutput); if (DxgiOutput && (hr != DXGI_ERROR_NOT_FOUND)) { DXGI_OUTPUT_DESC DesktopDesc; DxgiOutput->GetDesc(&DesktopDesc); DeskBounds->left = min(DesktopDesc.DesktopCoordinates.left, DeskBounds->left); DeskBounds->top = min(DesktopDesc.DesktopCoordinates.top, DeskBounds->top); DeskBounds->right = max(DesktopDesc.DesktopCoordinates.right, DeskBounds->right); DeskBounds->bottom = max(DesktopDesc.DesktopCoordinates.bottom, DeskBounds->bottom); } } --OutputCount; } else { hr = DxgiAdapter->EnumOutputs(SingleOutput, &DxgiOutput); if (FAILED(hr)) { DxgiAdapter->Release(); DxgiAdapter = nullptr; return ProcessFailure(m_Device, L"Output specified to be duplicated does not exist", L"Error", hr); } DXGI_OUTPUT_DESC DesktopDesc; DxgiOutput->GetDesc(&DesktopDesc); *DeskBounds = DesktopDesc.DesktopCoordinates; DxgiOutput->Release(); DxgiOutput = nullptr; OutputCount = 1; } DxgiAdapter->Release(); DxgiAdapter = nullptr; // Set passed in output count variable *OutCount = OutputCount; if (OutputCount == 0) { // We could not find any outputs, the system must be in a transition so return expected error // so we will attempt to recreate return DUPL_RETURN_ERROR_EXPECTED; } // Create shared texture for all duplication threads to draw into D3D11_TEXTURE2D_DESC DeskTexD; RtlZeroMemory(&DeskTexD, sizeof(D3D11_TEXTURE2D_DESC)); DeskTexD.Width = DeskBounds->right - DeskBounds->left; DeskTexD.Height = DeskBounds->bottom - DeskBounds->top; DeskTexD.MipLevels = 1; DeskTexD.ArraySize = 1; DeskTexD.Format = DXGI_FORMAT_B8G8R8A8_UNORM; DeskTexD.SampleDesc.Count = 1; DeskTexD.Usage = D3D11_USAGE_DEFAULT; DeskTexD.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; DeskTexD.CPUAccessFlags = 0; DeskTexD.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX; hr = m_Device->CreateTexture2D(&DeskTexD, nullptr, &m_SharedSurf); if (FAILED(hr)) { if (OutputCount != 1) { // If we are duplicating the complete desktop we try to create a single texture to hold the // complete desktop image and blit updates from the per output DDA interface. The GPU can // always support a texture size of the maximum resolution of any single output but there is no // guarantee that it can support a texture size of the desktop. // The sample only use this large texture to display the desktop image in a single window using DX // we could revert back to using GDI to update the window in this failure case. return ProcessFailure(m_Device, L"Failed to create DirectX shared texture - we are attempting to create a texture the size of the complete desktop and this may be larger than the maximum texture size of your GPU. Please try again using the -output command line parameter to duplicate only 1 monitor or configure your computer to a single monitor configuration", L"Error", hr, SystemTransitionsExpectedErrors); } else { return ProcessFailure(m_Device, L"Failed to create shared texture", L"Error", hr, SystemTransitionsExpectedErrors); } } // Get keyed mutex hr = m_SharedSurf->QueryInterface(__uuidof(IDXGIKeyedMutex), reinterpret_cast<void**>(&m_KeyMutex)); if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to query for keyed mutex in OUTPUTMANAGER", L"Error", hr); } return DUPL_RETURN_SUCCESS; }
//-------------------------------------------------------------------------------------- // Create Direct3D device and swap chain //-------------------------------------------------------------------------------------- HRESULT InitDevice() { HRESULT hr = S_OK; RECT rc; GetClientRect( g_hWnd, &rc ); UINT width = rc.right - rc.left; UINT height = rc.bottom - rc.top; UINT createDeviceFlags = 0; #ifdef _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, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, }; UINT numFeatureLevels = ARRAYSIZE( featureLevels ); for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ ) { g_driverType = driverTypes[driverTypeIndex]; hr = D3D11CreateDevice( nullptr, g_driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext ); if ( hr == E_INVALIDARG ) { // DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it hr = D3D11CreateDevice( nullptr, g_driverType, nullptr, createDeviceFlags, &featureLevels[1], numFeatureLevels - 1, D3D11_SDK_VERSION, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext ); } if( SUCCEEDED( hr ) ) break; } if( FAILED( hr ) ) return hr; // Obtain DXGI factory from device (since we used nullptr for pAdapter above) IDXGIFactory1* dxgiFactory = nullptr; { IDXGIDevice* dxgiDevice = nullptr; hr = g_pd3dDevice->QueryInterface( __uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice) ); if (SUCCEEDED(hr)) { IDXGIAdapter* adapter = nullptr; hr = dxgiDevice->GetAdapter(&adapter); if (SUCCEEDED(hr)) { hr = adapter->GetParent( __uuidof(IDXGIFactory1), reinterpret_cast<void**>(&dxgiFactory) ); adapter->Release(); } dxgiDevice->Release(); } } if (FAILED(hr)) return hr; // Create swap chain IDXGIFactory2* dxgiFactory2 = nullptr; hr = dxgiFactory->QueryInterface( __uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2) ); if ( dxgiFactory2 ) { // DirectX 11.1 or later hr = g_pd3dDevice->QueryInterface( __uuidof(ID3D11Device1), reinterpret_cast<void**>(&g_pd3dDevice1) ); if (SUCCEEDED(hr)) { (void) g_pImmediateContext->QueryInterface( __uuidof(ID3D11DeviceContext1), reinterpret_cast<void**>(&g_pImmediateContext1) ); } DXGI_SWAP_CHAIN_DESC1 sd; ZeroMemory(&sd, sizeof(sd)); sd.Width = width; sd.Height = height; sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.BufferCount = 1; hr = dxgiFactory2->CreateSwapChainForHwnd( g_pd3dDevice, g_hWnd, &sd, nullptr, nullptr, &g_pSwapChain1 ); if (SUCCEEDED(hr)) { hr = g_pSwapChain1->QueryInterface( __uuidof(IDXGISwapChain), reinterpret_cast<void**>(&g_pSwapChain) ); } dxgiFactory2->Release(); } else { // DirectX 11.0 systems DXGI_SWAP_CHAIN_DESC sd; ZeroMemory(&sd, sizeof(sd)); sd.BufferCount = 1; sd.BufferDesc.Width = width; sd.BufferDesc.Height = height; sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 60; sd.BufferDesc.RefreshRate.Denominator = 1; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.OutputWindow = g_hWnd; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.Windowed = TRUE; hr = dxgiFactory->CreateSwapChain( g_pd3dDevice, &sd, &g_pSwapChain ); } // Note this tutorial doesn't handle full-screen swapchains so we block the ALT+ENTER shortcut dxgiFactory->MakeWindowAssociation( g_hWnd, DXGI_MWA_NO_ALT_ENTER ); dxgiFactory->Release(); if (FAILED(hr)) return hr; // Create a render target view ID3D11Texture2D* pBackBuffer = nullptr; hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), reinterpret_cast<void**>( &pBackBuffer ) ); if( FAILED( hr ) ) return hr; hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, nullptr, &g_pRenderTargetView ); pBackBuffer->Release(); if( FAILED( hr ) ) return hr; g_pImmediateContext->OMSetRenderTargets( 1, &g_pRenderTargetView, nullptr ); // Setup the viewport D3D11_VIEWPORT vp; vp.Width = (FLOAT)width; vp.Height = (FLOAT)height; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0; vp.TopLeftY = 0; g_pImmediateContext->RSSetViewports( 1, &vp ); // Compile the vertex shader ID3DBlob* pVSBlob = nullptr; hr = CompileShaderFromFile( L"Tutorial02.fx", "VS", "vs_4_0", &pVSBlob ); if( FAILED( hr ) ) { MessageBox( nullptr, "The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", "Error", MB_OK ); return hr; } // Create the vertex shader hr = g_pd3dDevice->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), nullptr, &g_pVertexShader ); if( FAILED( hr ) ) { pVSBlob->Release(); return hr; } // Define the input layout D3D11_INPUT_ELEMENT_DESC layout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; UINT numElements = ARRAYSIZE( layout ); // Create the input layout hr = g_pd3dDevice->CreateInputLayout( layout, numElements, pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), &g_pVertexLayout ); pVSBlob->Release(); if( FAILED( hr ) ) return hr; // Set the input layout g_pImmediateContext->IASetInputLayout( g_pVertexLayout ); // Compile the pixel shader ID3DBlob* pPSBlob = nullptr; hr = CompileShaderFromFile( L"Tutorial02.fx", "PS", "ps_4_0", &pPSBlob ); if( FAILED( hr ) ) { MessageBox( nullptr, "The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", "Error", MB_OK ); return hr; } // Create the pixel shader hr = g_pd3dDevice->CreatePixelShader( pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), nullptr, &g_pPixelShader ); pPSBlob->Release(); if( FAILED( hr ) ) return hr; // Create vertex buffer SimpleVertex vertices[] = { XMFLOAT3( 0.0f, 0.5f, 0.5f ), XMFLOAT3( 0.5f, -0.5f, 0.5f ), XMFLOAT3( -0.5f, -0.5f, 0.5f ), }; D3D11_BUFFER_DESC bd; ZeroMemory( &bd, sizeof(bd) ); bd.Usage = D3D11_USAGE_DEFAULT; bd.ByteWidth = sizeof( SimpleVertex ) * 3; bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; bd.CPUAccessFlags = 0; D3D11_SUBRESOURCE_DATA InitData; ZeroMemory( &InitData, sizeof(InitData) ); InitData.pSysMem = vertices; hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer ); if( FAILED( hr ) ) return hr; // Set vertex buffer UINT stride = sizeof( SimpleVertex ); UINT offset = 0; g_pImmediateContext->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, &offset ); // Set primitive topology g_pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST ); return S_OK; }
// // Initialize all state // DUPL_RETURN OUTPUTMANAGER::InitOutput(HWND Window, INT SingleOutput, _Out_ UINT* OutCount, _Out_ RECT* DeskBounds) { HRESULT hr; // Store window handle m_WindowHandle = Window; // Driver types supported D3D_DRIVER_TYPE DriverTypes[] = { D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP, D3D_DRIVER_TYPE_REFERENCE, }; UINT NumDriverTypes = ARRAYSIZE(DriverTypes); // Feature levels supported D3D_FEATURE_LEVEL FeatureLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_1 }; UINT NumFeatureLevels = ARRAYSIZE(FeatureLevels); D3D_FEATURE_LEVEL FeatureLevel; // Create device for (UINT DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex) { hr = D3D11CreateDevice(nullptr, DriverTypes[DriverTypeIndex], nullptr, 0, FeatureLevels, NumFeatureLevels, D3D11_SDK_VERSION, &m_Device, &FeatureLevel, &m_DeviceContext); if (SUCCEEDED(hr)) { // Device creation succeeded, no need to loop anymore break; } } if (FAILED(hr)) { return ProcessFailure(m_Device, L"Device creation in OUTPUTMANAGER failed", L"Error", hr, SystemTransitionsExpectedErrors); } // Get DXGI factory IDXGIDevice* DxgiDevice = nullptr; hr = m_Device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&DxgiDevice)); if (FAILED(hr)) { return ProcessFailure(nullptr, L"Failed to QI for DXGI Device", L"Error", hr, nullptr); } IDXGIAdapter* DxgiAdapter = nullptr; hr = DxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&DxgiAdapter)); DxgiDevice->Release(); DxgiDevice = nullptr; if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to get parent DXGI Adapter", L"Error", hr, SystemTransitionsExpectedErrors); } hr = DxgiAdapter->GetParent(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&m_Factory)); DxgiAdapter->Release(); DxgiAdapter = nullptr; if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to get parent DXGI Factory", L"Error", hr, SystemTransitionsExpectedErrors); } // Register for occlusion status windows message hr = m_Factory->RegisterOcclusionStatusWindow(Window, OCCLUSION_STATUS_MSG, &m_OcclusionCookie); if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to register for occlusion message", L"Error", hr, SystemTransitionsExpectedErrors); } // Get window size RECT WindowRect; GetClientRect(m_WindowHandle, &WindowRect); UINT Width = WindowRect.right - WindowRect.left; UINT Height = WindowRect.bottom - WindowRect.top; // Create swapchain for window DXGI_SWAP_CHAIN_DESC1 SwapChainDesc; RtlZeroMemory(&SwapChainDesc, sizeof(SwapChainDesc)); SwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; SwapChainDesc.BufferCount = 2; SwapChainDesc.Width = Width; SwapChainDesc.Height = Height; SwapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; SwapChainDesc.SampleDesc.Count = 1; SwapChainDesc.SampleDesc.Quality = 0; hr = m_Factory->CreateSwapChainForHwnd(m_Device, Window, &SwapChainDesc, nullptr, nullptr, &m_SwapChain); if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to create window swapchain", L"Error", hr, SystemTransitionsExpectedErrors); } // Disable the ALT-ENTER shortcut for entering full-screen mode hr = m_Factory->MakeWindowAssociation(Window, DXGI_MWA_NO_ALT_ENTER); if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to make window association", L"Error", hr, SystemTransitionsExpectedErrors); } // Create shared texture DUPL_RETURN Return = CreateSharedSurf(SingleOutput, OutCount, DeskBounds); if (Return != DUPL_RETURN_SUCCESS) { return Return; } // Make new render target view Return = MakeRTV(); if (Return != DUPL_RETURN_SUCCESS) { return Return; } // Set view port SetViewPort(Width, Height); // Create the sample state D3D11_SAMPLER_DESC SampDesc; RtlZeroMemory(&SampDesc, sizeof(SampDesc)); SampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; SampDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; SampDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; SampDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; SampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; SampDesc.MinLOD = 0; SampDesc.MaxLOD = D3D11_FLOAT32_MAX; hr = m_Device->CreateSamplerState(&SampDesc, &m_SamplerLinear); if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to create sampler state in OUTPUTMANAGER", L"Error", hr, SystemTransitionsExpectedErrors); } // Create the blend state D3D11_BLEND_DESC BlendStateDesc; BlendStateDesc.AlphaToCoverageEnable = FALSE; BlendStateDesc.IndependentBlendEnable = FALSE; BlendStateDesc.RenderTarget[0].BlendEnable = TRUE; BlendStateDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; BlendStateDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; BlendStateDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; BlendStateDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; BlendStateDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; BlendStateDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; BlendStateDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; hr = m_Device->CreateBlendState(&BlendStateDesc, &m_BlendState); if (FAILED(hr)) { return ProcessFailure(m_Device, L"Failed to create blend state in OUTPUTMANAGER", L"Error", hr, SystemTransitionsExpectedErrors); } // Initialize shaders Return = InitShaders(); if (Return != DUPL_RETURN_SUCCESS) { return Return; } GetWindowRect(m_WindowHandle, &WindowRect); MoveWindow(m_WindowHandle, WindowRect.left, WindowRect.top, (DeskBounds->right - DeskBounds->left) / 2, (DeskBounds->bottom - DeskBounds->top) / 2, TRUE); return Return; }