public TextureCache(ColorTextures colorTextures, RenderHost renderHost)
 {
     this.colorTextures = colorTextures;
     this.renderHost    = renderHost;
     textures           = new ConcurrentDictionary <string, TextureAndSRV>();
 }
        public Renderer(IWin32Window form, RenderHost renderHost, ColorTextures colorTextures, TextureCache textureCache)
        {
            this.renderHost    = renderHost;
            this.textureCache  = textureCache;
            this.colorTextures = colorTextures;
            sceneElements      = new List <SceneElement>();

            // SwapChain description
            var desc = new SwapChainDescription()
            {
                BufferCount       = 1,
                ModeDescription   = new ModeDescription(100, 100, new Rational(60, 1), Format.R8G8B8A8_UNorm),
                IsWindowed        = true,
                OutputHandle      = form.Handle,
                SampleDescription = new SampleDescription(1, 0),
                SwapEffect        = SwapEffect.Discard,
                Usage             = Usage.RenderTargetOutput
            };

         #if DEBUG
            var flag = DeviceCreationFlags.Debug;
         #else
            var flag = DeviceCreationFlags.None;
         #endif

            // Create Device and SwapChain
            Device.CreateWithSwapChain(DriverType.Hardware, flag | DeviceCreationFlags.BgraSupport, desc, out device, out swapChain);
            immediateContext = device.ImmediateContext;

            // Initialize helper classes
            colorTextures.Initialize(device);
            textureCache.Initialize(device);

            // Load the Vertex and Pixel shaders
            ShaderBytecode vertexShaderByteCode;
            using (var stream = new MemoryStream(Resources.vs)) {
                vertexShaderByteCode = ShaderBytecode.FromStream(stream);
                vertexShader         = new VertexShader(device, vertexShaderByteCode);
            }
            immediateContext.VertexShader.Set(vertexShader);

            ShaderBytecode pixelShaderByteCode;
            using (var stream = new MemoryStream(Resources.ps)) {
                pixelShaderByteCode = ShaderBytecode.FromStream(stream);
                pixelShader         = new PixelShader(device, pixelShaderByteCode);
            }
            immediateContext.PixelShader.Set(pixelShader);

            // Create the input layout for the COMPLEX vertex
            inputLayout = new InputLayout(device, ShaderSignature.GetInputSignature(vertexShaderByteCode), new[] {
                new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
                new InputElement("TEXCOORD", 0, Format.R32G32_Float, 16, 0)
            });
            immediateContext.InputAssembler.InputLayout       = inputLayout;
            immediateContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;

            // Release the bytecode
            vertexShaderByteCode.Dispose();
            pixelShaderByteCode.Dispose();

            // Create Constant Buffer
            vertexShaderPerFrameConstantBuffer = new Buffer(device, Utilities.SizeOf <Matrix>(), ResourceUsage.Default, BindFlags.ConstantBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
            immediateContext.VertexShader.SetConstantBuffer(0, vertexShaderPerFrameConstantBuffer);

            // Create the default texture sampler
            textureSamplerWrap = new SamplerState(device, new SamplerStateDescription {
                Filter             = Filter.MinMagMipPoint,
                AddressU           = TextureAddressMode.Wrap,
                AddressV           = TextureAddressMode.Wrap,
                AddressW           = TextureAddressMode.Wrap,
                BorderColor        = new Color4(0.0f, 0.0f, 0.0f, 0.0f),
                ComparisonFunction = Comparison.Always,
                MaximumAnisotropy  = 16,
                MipLodBias         = 0,
                MinimumLod         = 0,
                MaximumLod         = 3.402823466e+38f//D3D11_FLOAT32_MAX
            });

            textureSamplerBorder = new SamplerState(device, new SamplerStateDescription {
                Filter             = Filter.MinMagMipPoint,
                AddressU           = TextureAddressMode.Border,
                AddressV           = TextureAddressMode.Border,
                AddressW           = TextureAddressMode.Border,
                BorderColor        = new Color4(0.0f, 0.0f, 0.0f, 0.0f),
                ComparisonFunction = Comparison.Always,
                MaximumAnisotropy  = 16,
                MipLodBias         = 0,
                MinimumLod         = 0,
                MaximumLod         = 3.402823466e+38f//D3D11_FLOAT32_MAX
            });

            // Prepare the camera
            Camera = new Camera();

            // Create the depth stencil state
            depthStencilState = new DepthStencilState(device, new DepthStencilStateDescription {
                IsDepthEnabled   = true,
                DepthWriteMask   = DepthWriteMask.All,
                DepthComparison  = Comparison.GreaterEqual,
                IsStencilEnabled = false,
                StencilReadMask  = 0xff, //D3D11_DEFAULT_STENCIL_READ_MASK
                StencilWriteMask = 0xff, //D3D11_DEFAULT_STENCIL_WRITE_MASK
                FrontFace        = new DepthStencilOperationDescription {
                    DepthFailOperation = StencilOperation.Keep,
                    FailOperation      = StencilOperation.Keep,
                    PassOperation      = StencilOperation.Replace,
                    Comparison         = Comparison.Always
                },
                BackFace = new DepthStencilOperationDescription {
                    DepthFailOperation = StencilOperation.Keep,
                    FailOperation      = StencilOperation.Keep,
                    PassOperation      = StencilOperation.Replace,
                    Comparison         = Comparison.Always
                }
            });

            // Create the raster state
            defaultRastState = new RasterizerState(device, new RasterizerStateDescription {
                IsAntialiasedLineEnabled = false,
                CullMode                = CullMode.Back,
                DepthBias               = 0,
                DepthBiasClamp          = 0.0f,
                IsDepthClipEnabled      = true,
                FillMode                = FillMode.Solid,
                IsFrontCounterClockwise = false,
                IsMultisampleEnabled    = true,
                IsScissorEnabled        = false,
                SlopeScaledDepthBias    = 0
            });
            wireframeOverlayRastState = new RasterizerState(device, new RasterizerStateDescription {
                IsAntialiasedLineEnabled = false,
                CullMode                = CullMode.Back,
                DepthBias               = (int)(Math.Pow(2.0, 23.0) / 1000),
                DepthBiasClamp          = 0.001f,
                IsDepthClipEnabled      = true,
                FillMode                = FillMode.Wireframe,
                IsFrontCounterClockwise = false,
                IsMultisampleEnabled    = true,
                IsScissorEnabled        = false,
                SlopeScaledDepthBias    = 0
            });


            // Create the blend state
            var blendDesc = new BlendStateDescription {
                AlphaToCoverageEnable  = false,
                IndependentBlendEnable = false
            };

            for (var i = 0; i < 8; ++i)
            {
                blendDesc.RenderTarget[i].IsBlendEnabled        = true;
                blendDesc.RenderTarget[i].BlendOperation        = BlendOperation.Add;
                blendDesc.RenderTarget[i].AlphaBlendOperation   = BlendOperation.Add;
                blendDesc.RenderTarget[i].DestinationBlend      = BlendOption.InverseSourceAlpha;
                blendDesc.RenderTarget[i].DestinationAlphaBlend = BlendOption.One;
                blendDesc.RenderTarget[i].RenderTargetWriteMask = ColorWriteMaskFlags.All;
                blendDesc.RenderTarget[i].SourceBlend           = BlendOption.SourceAlpha;
                blendDesc.RenderTarget[i].SourceAlphaBlend      = BlendOption.One;
            }

            blendState = new BlendState(device, blendDesc);

            // Prepare the stages that don't change per frame
            immediateContext.OutputMerger.SetDepthStencilState(depthStencilState);
            immediateContext.OutputMerger.SetBlendState(blendState);
            immediateContext.PixelShader.SetSampler(0, textureSamplerWrap);
        }