	ID3D11InputLayout* input_layout;
		HRESULT hr = device_->CreateInputLayout(desc.data(), desc.size(), shader->GetCode().data(), shader->GetCode().size(), &input_layout);
		assert(SUCCEEDED(hr));

		return make_shared<WindowsInputLayout>(input_layout);
	}

	shared_ptr<IShader> WindowsDevice::CreateVertexShader(const string& name, const std::vector<char>& code)
	{
		ID3D11VertexShader* shader;
		HRESULT hr = device_->CreateVertexShader(code.data(), code.size(), nullptr, &shader);
		assert(SUCCEEDED(hr));

		ID3D11ShaderReflection* shader_reflection;
		ID3D11Buffer* constant_buffer;
		int constant_buffer_size;
		PrepareShaderReflection(code, &shader_reflection, &constant_buffer_size);
		PrepareConstantBuffer(constant_buffer_size, &constant_buffer);
		
		return make_shared<WindowsShader<ID3D11VertexShader>>(name, code, shader, shader_reflection, constant_buffer, constant_buffer_size);
	}

	shared_ptr<IShader> WindowsDevice::CreatePixelShader(const string& name, const std::vector<char>& code)
	{
		ID3D11PixelShader* shader;
		HRESULT hr = device_->CreatePixelShader(code.data(), code.size(), nullptr, &shader);
		assert(SUCCEEDED(hr));

		ID3D11ShaderReflection* shader_reflection;
		ID3D11Buffer* constant_buffer;
		int constant_buffer_size;
		PrepareShaderReflection(code, &shader_reflection, &constant_buffer_size);
		PrepareConstantBuffer(constant_buffer_size, &constant_buffer);

		return make_shared<WindowsShader<ID3D11PixelShader>>(name, code, shader, shader_reflection, constant_buffer, constant_buffer_size);
	}

	shared_ptr<IPipelineState> WindowsDevice::CreatePipelineState()
	{
		D3D11_DEPTH_STENCIL_DESC depth_stencil_desc;
		depth_stencil_desc.DepthEnable = true;
		depth_stencil_desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
		depth_stencil_desc.DepthFunc = D3D11_COMPARISON_LESS;
		depth_stencil_desc.StencilEnable = false;
		depth_stencil_desc.StencilReadMask = 0xFF;
		depth_stencil_desc.StencilWriteMask = 0xFF;
		depth_stencil_desc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
		depth_stencil_desc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
		depth_stencil_desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
		depth_stencil_desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
		depth_stencil_desc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
		depth_stencil_desc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
		depth_stencil_desc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
		depth_stencil_desc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
		ID3D11DepthStencilState* depth_stencil;
		HRESULT hr = device_->CreateDepthStencilState(&depth_stencil_desc, &depth_stencil);
		assert(SUCCEEDED(hr));

		D3D11_RASTERIZER_DESC rasterizer_desc;
		rasterizer_desc.AntialiasedLineEnable = false;
		rasterizer_desc.CullMode = D3D11_CULL_BACK;
		rasterizer_desc.DepthBias = 0;
		rasterizer_desc.DepthBiasClamp = 0.0f;
		rasterizer_desc.DepthClipEnable = true;
		rasterizer_desc.FillMode = D3D11_FILL_SOLID;
		rasterizer_desc.FrontCounterClockwise = true;
		rasterizer_desc.MultisampleEnable = false;
		rasterizer_desc.ScissorEnable = false;
		rasterizer_desc.SlopeScaledDepthBias = 0.0f;
		ID3D11RasterizerState* rasterizer;
		hr = device_->CreateRasterizerState(&rasterizer_desc, &rasterizer);
		assert(SUCCEEDED(hr));

		D3D11_BLEND_DESC blend_desc;
		blend_desc.AlphaToCoverageEnable = false;
		blend_desc.IndependentBlendEnable = false;
		blend_desc.RenderTarget[0].BlendEnable = false;
		blend_desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
		blend_desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
		blend_desc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
		blend_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
		blend_desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
		blend_desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
		blend_desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
		ID3D11BlendState* blend;
		hr = device_->CreateBlendState(&blend_desc, &blend);
		assert(SUCCEEDED(hr));
		
		return make_shared<WindowsPipelineState>(rasterizer, depth_stencil, blend);
	}

	void WindowsDevice::SetPrimitiveTopology(PrimitiveTopology topology)
	{
		device_context_->IASetPrimitiveTopology(gTopologyMap[topology]);
	}

	void WindowsDevice::SetRenderTarget(shared_ptr<IRenderTarget> render_target)
	{
		shared_ptr<WindowsRenderTarget> windows_render_target = static_pointer_cast<WindowsRenderTarget>(render_target);
		current_render_target_ = windows_render_target;

		// Only support one render target now
		ID3D11RenderTargetView* render_target_views[] = { windows_render_target->GetRenderTargetView() };
		device_context_->OMSetRenderTargets(1, render_target_views, windows_render_target->GetDepthStencilView());

		D3D11_VIEWPORT vp;
		vp.TopLeftX = 0.0f;
		vp.TopLeftY = 0.0f;
		vp.Width = static_cast<float>(windows_render_target->GetWidth());
		vp.Height = static_cast<float>(windows_render_target->GetHeight());
		vp.MinDepth = 0.0f;
		vp.MaxDepth = 1.0f;
		device_context_->RSSetViewports(1, &vp);
	}

	void WindowsDevice::SetInputLayout(shared_ptr<IInputLayout> input_layout)
	{
		shared_ptr<WindowsInputLayout> layout = static_pointer_cast<WindowsInputLayout>(input_layout);
		device_context_->IASetInputLayout(layout->GetInputLayout());
	}

	void WindowsDevice::SetVertexShader(shared_ptr<IShader> vertex_shader)
	{
		shared_ptr<WindowsShader<ID3D11VertexShader>> shader = static_pointer_cast<WindowsShader<ID3D11VertexShader>>(vertex_shader);
		device_context_->VSSetShader(shader->GetShader(), nullptr, 0);
		UpdateConstantBuffer(shader);
	}
	void WindowsDevice::SetPixelShader(shared_ptr<IShader> pixel_shader)
	{
		shared_ptr<WindowsShader<ID3D11PixelShader>> shader = static_pointer_cast<WindowsShader<ID3D11