#include "Graphics.h" #include "dxerr.h" #include #include #include #include "GraphicsThrowMacros.h" namespace wrl = Microsoft::WRL; namespace dx = DirectX; #pragma comment(lib,"d3d11.lib") #pragma comment(lib,"D3DCompiler.lib") Graphics::Graphics( HWND hWnd ) { // 交换链的参数定义 DXGI_SWAP_CHAIN_DESC sd = {}; sd.BufferDesc.Width = 0; sd.BufferDesc.Height = 0; sd.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; sd.BufferDesc.RefreshRate.Numerator = 0; sd.BufferDesc.RefreshRate.Denominator = 0; sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; sd.SampleDesc.Count = 1; sd.SampleDesc.Quality = 0; sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; sd.BufferCount = 1; sd.OutputWindow = hWnd; sd.Windowed = TRUE; sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; sd.Flags = 0; UINT swapCreateFlags = 0u; #ifndef NDEBUG swapCreateFlags |= D3D11_CREATE_DEVICE_DEBUG; #endif // for checking results of d3d functions HRESULT hr; // create device and front/back buffers, and swap chain and rendering context // 创建Device,SwapChain和Context GFX_THROW_INFO(D3D11CreateDeviceAndSwapChain( nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, swapCreateFlags, nullptr, 0, D3D11_SDK_VERSION, &sd, &pSwap, &pDevice, nullptr, &pContext )); // gain access to texture subresource in swap chain (back buffer) wrl::ComPtr pBackBuffer; GFX_THROW_INFO(pSwap->GetBuffer(0, __uuidof(ID3D11Resource), &pBackBuffer)); GFX_THROW_INFO(pDevice->CreateRenderTargetView(pBackBuffer.Get(), nullptr, &pTarget)); // Create depth stencil state D3D11_DEPTH_STENCIL_DESC depthStencilDesc = {}; depthStencilDesc.DepthEnable = TRUE; depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS; wrl::ComPtr pDepthStencilState; // Create depth stencil state GFX_THROW_INFO(pDevice->CreateDepthStencilState(&depthStencilDesc, &pDepthStencilState)); // bind depth state pContext->OMSetDepthStencilState(pDepthStencilState.Get(), 1u); // Create the depth stencil texture wrl::ComPtr depthStencilTexture; D3D11_TEXTURE2D_DESC depthStencilTextureDesc = {}; depthStencilTextureDesc.Width = 800; depthStencilTextureDesc.Height = 600; depthStencilTextureDesc.MipLevels = 1u; depthStencilTextureDesc.ArraySize = 1u; depthStencilTextureDesc.Format = DXGI_FORMAT_D32_FLOAT; depthStencilTextureDesc.SampleDesc.Count = 1u; depthStencilTextureDesc.SampleDesc.Quality = 0u; depthStencilTextureDesc.Usage = D3D11_USAGE_DEFAULT; depthStencilTextureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; GFX_THROW_INFO(pDevice->CreateTexture2D(&depthStencilTextureDesc, nullptr, &depthStencilTexture)); // Create the depth stencil view D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc = {}; depthStencilViewDesc.Format = DXGI_FORMAT_D32_FLOAT; depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; depthStencilViewDesc.Texture2D.MipSlice = 0u; GFX_THROW_INFO(pDevice->CreateDepthStencilView(depthStencilTexture.Get(), &depthStencilViewDesc, &pDSView)); // Bind depth stencil view to out put merger pContext->OMSetRenderTargets(1u, pTarget.GetAddressOf(), pDSView.Get()); // configure viewport D3D11_VIEWPORT vp; vp.Width = 800.0f; vp.Height = 600.0f; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; vp.TopLeftX = 0.0f; vp.TopLeftY = 0.0f; pContext->RSSetViewports(1u, &vp); } void Graphics::EndFrame() { // flipping,使用SwapChain将back buffer的内容展现到屏幕 HRESULT hr; #ifndef NDEBUG infoManager.Set(); #endif if (FAILED(hr = pSwap->Present(1u, 0u))) // 同步频率1,代表屏幕每刷新一次,就进行图形刷新。 { if (hr == DXGI_ERROR_DEVICE_REMOVED) { throw GFX_DEVICE_REMOVED_EXCEPT(pDevice->GetDeviceRemovedReason()); } else { throw GFX_EXCEPT(hr); } } } void Graphics::ClearBuffer(float red, float green, float blue) noexcept { const float color[] = { red,green,blue,1.0f }; pContext->ClearRenderTargetView(pTarget.Get(), color); pContext->ClearDepthStencilView(pDSView.Get(), D3D11_CLEAR_DEPTH, 1.0f, 0u); } void Graphics::DrawIndexed(UINT count) noexcept(!IS_DEBUG) { GFX_THROW_INFO_ONLY( pContext->DrawIndexed( count,0u,0u ) ); } void Graphics::SetProjection( DirectX::FXMMATRIX proj ) noexcept { projection = proj; } DirectX::XMMATRIX Graphics::GetProjection() const noexcept { return projection; } // Graphics exception stuff Graphics::HrException::HrException(int line, const char* file, HRESULT hr, std::vector infoMsgs) noexcept : Exception(line, file), hr(hr) { // join all info messages with newlines into single string for (const auto& m : infoMsgs) { info += m; info.push_back('\n'); } // remove final newline if exists if (!info.empty()) { info.pop_back(); } } const char* Graphics::HrException::what() const noexcept { std::ostringstream oss; oss << GetType() << std::endl << "[Error Code] 0x" << std::hex << std::uppercase << GetErrorCode() << std::dec << " (" << (unsigned long)GetErrorCode() << ")" << std::endl << "[Error String] " << GetErrorString() << std::endl << "[Description] " << GetErrorDescription() << std::endl; if (!info.empty()) { oss << "\n[Error Info]\n" << GetErrorInfo() << std::endl << std::endl; } oss << GetOriginString(); whatBuffer = oss.str(); return whatBuffer.c_str(); } const char* Graphics::HrException::GetType() const noexcept { return "Chili Graphics Exception"; } HRESULT Graphics::HrException::GetErrorCode() const noexcept { return hr; } std::string Graphics::HrException::GetErrorString() const noexcept { return DXGetErrorString(hr); } std::string Graphics::HrException::GetErrorDescription() const noexcept { char buf[512]; DXGetErrorDescription(hr, buf, sizeof(buf)); return buf; } std::string Graphics::HrException::GetErrorInfo() const noexcept { return info; } const char* Graphics::DeviceRemovedException::GetType() const noexcept { return "Chili Graphics Exception [Device Removed] (DXGI_ERROR_DEVICE_REMOVED)"; } Graphics::InfoException::InfoException(int line, const char* file, std::vector infoMsgs) noexcept : Exception(line, file) { // join all info messages with newlines into single string for (const auto& m : infoMsgs) { info += m; info.push_back('\n'); } // remove final newline if exists if (!info.empty()) { info.pop_back(); } } const char* Graphics::InfoException::what() const noexcept { std::ostringstream oss; oss << GetType() << std::endl << "\n[Error Info]\n" << GetErrorInfo() << std::endl << std::endl; oss << GetOriginString(); whatBuffer = oss.str(); return whatBuffer.c_str(); } const char* Graphics::InfoException::GetType() const noexcept { return "Chili Graphics Info Exception"; } std::string Graphics::InfoException::GetErrorInfo() const noexcept { return info; }