#include "xna-dx/framework.hpp" namespace xna { void GraphicsDeviceImplementation::Create(GraphicsAdapter& currentAdapter) { // See ref // // D3D_DRIVER_TYPE // https://learn.microsoft.com/en-us/windows/win32/api/d3dcommon/ne-d3dcommon-d3d_driver_type // D3D11CreateDevice function // https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-d3d11createdevice // auto createDeviceFlags = 0; #if _DEBUG createDeviceFlags = D3D11_CREATE_DEVICE_FLAG::D3D11_CREATE_DEVICE_DEBUG; #endif const auto& pAdapter = GraphicsAdapter::UseNullDevice() ? NULL : currentAdapter.Implementation->Adapter.Get(); // // if pAdapter is not NULL driverType must be D3D_DRIVER_TYPE_UNKNOWN // auto driverType = D3D_DRIVER_TYPE_UNKNOWN; if (GraphicsAdapter::UseReferenceDevice()) driverType = D3D_DRIVER_TYPE_WARP; else if (GraphicsAdapter::UseNullDevice()) driverType = D3D_DRIVER_TYPE_HARDWARE; auto hr = D3D11CreateDevice( //_In_opt_ IDXGIAdapter* pAdapter, pAdapter, //D3D_DRIVER_TYPE DriverType, driverType, //HMODULE Software, NULL, //UINT Flags, createDeviceFlags, //_In_reads_opt_( FeatureLevels ) CONST D3D_FEATURE_LEVEL* pFeatureLevels, FeatureLevels, //UINT FeatureLevels, static_cast(FeatureLevelCount), //UINT SDKVersion, D3D11_SDK_VERSION, //_COM_Outptr_opt_ ID3D11Device** ppDevice Device.GetAddressOf(), //_Out_opt_ D3D_FEATURE_LEVEL* pFeatureLevel, &CurrentFeatureLevel, //_COM_Outptr_opt_ ID3D11DeviceContext** ppImmediateContext Context.GetAddressOf()); if FAILED(hr) throw csharp::InvalidOperationException(); } void GraphicsDeviceImplementation::Reset() { if (Device) { Device->Release(); Device = nullptr; } if (Context) { Context->Release(); Context = nullptr; } if (Factory) { Factory->Release(); Factory = nullptr; } } static void initAndApplyState(P_BlendState& blendState, P_RasterizerState& rasterizerState, P_DepthStencilState& depthStencilState, P_SamplerStateCollection& samplerStates, P_GraphicsDevice const& device); GraphicsDevice::GraphicsDevice() { Implementation = unew(); adapter = GraphicsAdapter::DefaultAdapter(); } GraphicsDevice::GraphicsDevice(sptr const& adapter, GraphicsProfile const& graphicsProfile, sptr const& presentationParameters) : adapter(adapter), graphicsProfile(graphicsProfile), presentationParameters(presentationParameters) { Implementation = unew(); blendState = xna::BlendState::Opaque(); depthStencilState = xna::DepthStencilState::Default(); rasterizerState = xna::RasterizerState::CullCounterClockwise(); samplerStateCollection = snew(); } void GraphicsDevice::Initialize() { Implementation->Reset(); auto _this = shared_from_this(); Implementation->Create(*adapter); // // Background // const auto backColor = Colors::CornflowerBlue; const auto backColorV3 = backColor.ToVector3(); Implementation->backgroundColor[0] = backColorV3.X; Implementation->backgroundColor[1] = backColorV3.Y; Implementation->backgroundColor[2] = backColorV3.Z; Implementation->backgroundColor[3] = 1.0f; // // Window Association // auto hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)&Implementation->Factory); if FAILED(hr) throw csharp::InvalidOperationException(); auto hwnd = reinterpret_cast(presentationParameters->DeviceWindowHandle); hr = Implementation->Factory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER); if (FAILED(hr)) throw csharp::InvalidOperationException(); // // Viewport // viewport = xna::Viewport(0.0F, 0.0F, presentationParameters->BackBufferWidth, presentationParameters->BackBufferHeight, 0.0F, 1.F); D3D11_VIEWPORT view = DxHelpers::ViewportToDx(viewport); Implementation->Context->RSSetViewports(1, &view); // // States // initAndApplyState(blendState, rasterizerState, depthStencilState, samplerStateCollection, _this); // // Presentation // const auto currentPresenInterval = presentationParameters->PresentationInterval; switch (currentPresenInterval) { case PresentInterval::Default: case PresentInterval::One: case PresentInterval::Two: Implementation->vSyncValue = 1; break; case PresentInterval::Immediate: Implementation->vSyncValue = 0; break; default: Implementation->vSyncValue = 1; break; } Implementation->SwapChain = snew(_this); Implementation->SwapChain->Initialize(); // //Render Target // if (renderTarget) { renderTarget->Initialize(); Implementation->RenderTarget2D = renderTarget; } else { Implementation->RenderTarget2D = RenderTarget2D::FromBackBuffer(_this); } const auto& renderView = Implementation->RenderTarget2D->Implementation2->RenderTargetView; Implementation->Context->OMSetRenderTargets(1, renderView.GetAddressOf(), nullptr); } bool GraphicsDevice::Present() const { bool result = Implementation->SwapChain->Present(Implementation->vSyncValue != 0); Implementation->Context->OMSetRenderTargets( 1, Implementation->RenderTarget2D->Implementation2->RenderTargetView.GetAddressOf(), nullptr); return result; } void GraphicsDevice::Clear(Color const& color) const { if (!Implementation) return; const auto v4 = color.ToVector4(); Implementation->backgroundColor[0] = v4.X; Implementation->backgroundColor[1] = v4.Y; Implementation->backgroundColor[2] = v4.Z; Implementation->backgroundColor[3] = v4.W; Implementation->Context->ClearRenderTargetView( Implementation->RenderTarget2D->Implementation2->RenderTargetView.Get(), Implementation->backgroundColor); } void GraphicsDevice::Clear(ClearOptions options, Color const& color, float depth, Int stencil) const { if (!Implementation) return; switch (options) { case xna::ClearOptions::DepthBuffer: throw csharp::InvalidOperationException(); break; case xna::ClearOptions::Stencil: throw csharp::InvalidOperationException(); break; case xna::ClearOptions::Target: Clear(color); break; default: return; } } void GraphicsDevice::Viewport(xna::Viewport const& value) { viewport = value; const auto view = DxHelpers::ViewportToDx(viewport); Implementation->Context->RSSetViewports(1, &view); } void GraphicsDevice::BlendState(sptr const& value) { blendState = value; blendState->Apply(); } void GraphicsDevice::DepthStencilState(sptr const& value) { depthStencilState = value; depthStencilState->Apply(); } void GraphicsDevice::RasterizerState(sptr const& value) { rasterizerState = value; rasterizerState->Apply(); } void GraphicsDevice::Reset(sptr const& parameters, sptr const& graphicsAdapter) { Implementation = unew(); adapter = graphicsAdapter; presentationParameters = parameters; Initialize(); } // // INTERNAL // static void initAndApplyState(P_BlendState& blendState, P_RasterizerState& rasterizerState, P_DepthStencilState& depthStencilState, P_SamplerStateCollection& samplerStates, P_GraphicsDevice const& device) { blendState->Bind(device); blendState->Initialize(); blendState->Apply(); rasterizerState->Bind(device); rasterizerState->Initialize(); rasterizerState->Apply(); depthStencilState->Bind(device); depthStencilState->Initialize(); depthStencilState->Apply(); samplerStates->Apply(*device); } }