Пример #1
0
 internal virtual void PerFrame()
 {
     MyCommon.UpdateFrameConstants();
 }
Пример #2
0
        // viewport, render target
        internal unsafe static void Draw(IRtvBindable rtv, MyViewport viewport, IBlendState blendstate = null)
        {
            if (StackTop.m_internalBatch.Texture != null && StackTop.m_internalBatch.Count > 0)
            {
                StackTop.m_internalBatch.Commit();
            }
            StackTop.m_internalBatch = new MySpritesBatch();

            RC.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip);

            RC.SetInputLayout(m_inputLayout);
            //RC.SetScreenViewport();
            RC.SetViewport(viewport.OffsetX, viewport.OffsetY, viewport.Width, viewport.Height);

            RC.VertexShader.Set(m_vs);
            RC.AllShaderStages.SetConstantBuffer(MyCommon.FRAME_SLOT, MyCommon.FrameConstants);
            RC.AllShaderStages.SetConstantBuffer(MyCommon.PROJECTION_SLOT, MyCommon.GetObjectCB(64));
            RC.PixelShader.Set(m_ps);
            RC.PixelShader.SetSamplers(0, MySamplerStateManager.StandardSamplers);

            //RC.BindDepthRT(null, DepthStencilAccess.DepthReadOnly, MyRender11.Backbuffer);
            // to reset state
            RC.SetRtv(rtv);

            RC.SetBlendState(blendstate == null ? MyBlendStateManager.BlendAlphaPremult : blendstate);
            RC.SetDepthStencilState(MyDepthStencilStateManager.IgnoreDepthStencil, 0);

            CheckBufferSize(StackTop.m_instances.Count);
            RC.SetVertexBuffer(0, m_VB);

            var mapping = MyMapping.MapDiscard(m_VB);

            for (int i = 0; i < StackTop.m_instances.Count; i++)
            {
                var helper = StackTop.m_instances[i];
                mapping.WriteAndPosition(ref helper);
            }
            mapping.Unmap();

            mapping = MyMapping.MapDiscard(MyCommon.GetObjectCB(64));
            var viewportSize = new Vector2(viewport.Width, viewport.Height);

            mapping.WriteAndPosition(ref viewportSize);
            mapping.Unmap();

            foreach (var batch in StackTop.m_batches)
            {
                if (batch.ScissorRectangle.HasValue)
                {
                    RC.SetRasterizerState(MyRasterizerStateManager.ScissorTestRasterizerState);

                    var scissor = batch.ScissorRectangle.Value;
                    RC.SetScissorRectangle((int)scissor.X, (int)scissor.Y, (int)(scissor.X + scissor.Width), (int)(scissor.Y + scissor.Height));
                }
                else
                {
                    RC.SetRasterizerState(MyRasterizerStateManager.NocullRasterizerState);
                }

                RC.PixelShader.SetSrv(0, batch.Texture);
                RC.DrawInstanced(4, batch.Count, 0, batch.Start);
            }

            RC.SetBlendState(null);
            RC.SetRasterizerState(null);
            RC.SetPrimitiveTopology(PrimitiveTopology.TriangleList);

            StackTop.m_instances.Clear();
            StackTop.m_batches.Clear();
        }
Пример #3
0
        internal unsafe static void Render()
        {
            var RC = MyImmediateRC.RC;

            if (Atmospheres.Count == 0 || !Enabled)
            {
                return;
            }

            var sphereMesh = MyMeshes.GetMeshId(X.TEXT_("Models/Debug/Sphere.mwm"), 1.0f);
            var buffers    = MyMeshes.GetLodMesh(sphereMesh, 0).Buffers;

            RC.SetVertexBuffer(0, buffers.VB0.Buffer, buffers.VB0.Stride);
            RC.SetIndexBuffer(buffers.IB.Buffer, buffers.IB.Format);

            RC.VertexShader.Set(m_proxyVs);
            RC.SetInputLayout(m_proxyIL);


            RC.SetRasterizerState(null);
            RC.SetBlendState(MyBlendStateManager.BlendAtmosphere);

            RC.AllShaderStages.SetConstantBuffer(MyCommon.FRAME_SLOT, MyCommon.FrameConstants);

            var cb = MyCommon.GetObjectCB(sizeof(AtmosphereConstants));

            RC.AllShaderStages.SetConstantBuffer(1, cb);
            RC.PixelShader.SetSampler(MyCommon.SHADOW_SAMPLER_SLOT, MySamplerStateManager.Shadowmap);

            // depth,
            RC.PixelShader.SetSrvs(0, MyGBuffer.Main);

            RC.SetRtv(MyGBuffer.Main.DepthStencil, MyDepthStencilAccess.ReadOnly, MyGBuffer.Main.LBuffer);


            var indicesNum = MyMeshes.GetLodMesh(sphereMesh, 0).Info.IndicesNum;

            // sort by distance
            int i = Atmospheres.Count;

            foreach (var atmosphere in Atmospheres.OrderByDescending(x => (x.Value.WorldMatrix.Translation - MyRender11.Environment.Matrices.CameraPosition).LengthSquared()))
            {
                var worldMatrix = atmosphere.Value.WorldMatrix;
                worldMatrix.Translation -= MyRender11.Environment.Matrices.CameraPosition;

                var worldViewProj = ((Matrix)worldMatrix) * MyRender11.Environment.Matrices.ViewProjectionAt0;

                double distance       = worldMatrix.Translation.Length();
                double atmosphereTop  = atmosphere.Value.AtmosphereRadius * atmosphere.Value.Settings.AtmosphereTopModifier * atmosphere.Value.PlanetScaleFactor * atmosphere.Value.Settings.RayleighTransitionModifier;
                float  rayleighHeight = atmosphere.Value.Settings.RayleighHeight;
                float  t = 0.0f;
                if (distance > atmosphereTop)
                {
                    if (distance > atmosphereTop * 2.0f)
                    {
                        t = 1.0f;
                    }
                    else
                    {
                        t = (float)((distance - atmosphereTop) / atmosphereTop);
                    }
                }
                rayleighHeight = MathHelper.Lerp(atmosphere.Value.Settings.RayleighHeight, atmosphere.Value.Settings.RayleighHeightSpace, t);

                AtmosphereConstants constants = new AtmosphereConstants();
                constants.WorldViewProj    = Matrix.Transpose(worldViewProj);
                constants.PlanetCentre     = (Vector3)worldMatrix.Translation;
                constants.AtmosphereRadius = atmosphere.Value.AtmosphereRadius * atmosphere.Value.Settings.AtmosphereTopModifier;
                // Raise the ground a bit for better sunsets
                constants.GroundRadius           = atmosphere.Value.PlanetRadius * 1.01f * atmosphere.Value.Settings.SeaLevelModifier;
                constants.BetaRayleighScattering = atmosphere.Value.BetaRayleighScattering / atmosphere.Value.Settings.RayleighScattering;
                constants.BetaMieScattering      = atmosphere.Value.BetaMieScattering / atmosphere.Value.Settings.MieColorScattering;
                constants.HeightScaleRayleighMie = atmosphere.Value.HeightScaleRayleighMie * new Vector2(rayleighHeight, atmosphere.Value.Settings.MieHeight);
                constants.MieG = atmosphere.Value.Settings.MieG;
                constants.PlanetScaleFactor     = atmosphere.Value.PlanetScaleFactor;
                constants.AtmosphereScaleFactor = atmosphere.Value.AtmosphereScaleFactor;
                constants.Intensity             = atmosphere.Value.Settings.Intensity;
                constants.FogIntensity          = atmosphere.Value.Settings.FogIntensity;

                var mapping = MyMapping.MapDiscard(cb);
                mapping.WriteAndPosition(ref constants);
                mapping.Unmap();

                var luts = AtmosphereLUT[atmosphere.Key];
                RC.PixelShader.SetSrvs(5, luts.TransmittanceLut);

                bool inside = worldMatrix.Translation.Length() < atmosphere.Value.AtmosphereRadius * atmosphere.Value.PlanetScaleFactor;

                if (inside)
                {
                    RC.SetRasterizerState(MyRasterizerStateManager.InvTriRasterizerState);

                    if (MyRender11.MultisamplingEnabled)
                    {
                        RC.SetDepthStencilState(MyDepthStencilStateManager.TestEdgeStencil, 0);
                    }
                    else
                    {
                        RC.SetDepthStencilState(MyDepthStencilStateManager.IgnoreDepthStencil);
                    }
                }
                else
                {
                    RC.SetRasterizerState(null);

                    if (MyRender11.MultisamplingEnabled)
                    {
                        RC.SetDepthStencilState(MyDepthStencilStateManager.TestDepthAndEdgeStencil, 0);
                    }
                    else
                    {
                        RC.SetDepthStencilState(MyDepthStencilStateManager.DepthTestReadOnly);
                    }
                }

                RC.PixelShader.Set(m_ps);

                RC.DrawIndexed(indicesNum, 0, 0);

                if (MyRender11.MultisamplingEnabled)
                {
                    if (inside)
                    {
                        RC.SetDepthStencilState(MyDepthStencilStateManager.TestEdgeStencil, 0x80);
                    }
                    else
                    {
                        RC.SetDepthStencilState(MyDepthStencilStateManager.TestDepthAndEdgeStencil, 0x80);
                    }

                    RC.PixelShader.Set(m_psPerSample);
                    RC.DrawIndexed(indicesNum, 0, 0);
                }

                i--;
            }

            RC.PixelShader.SetSrvs(5, null, null);
            RC.SetRasterizerState(null);
            RC.SetDepthStencilState(null);
            RC.SetRtv(null);
        }
Пример #4
0
        static unsafe MyMaterialProxy_2 CreateProxy(MyVoxelMaterialTriple triple)
        {
            byte[] buffer;
            int    size;

            System.Diagnostics.Debug.Assert(triple.I0 < Table.Length, "Index to table incorrect");
            System.Diagnostics.Debug.Assert(triple.I1 < Table.Length, "Index to table incorrect");
            System.Diagnostics.Debug.Assert(triple.I2 < Table.Length, "Index to table incorrect");

            //TODO: This shouldnt happen if Table is created correctly
            if (triple.I0 >= Table.Length)
            {
                triple.I0 = 0;
            }
            if (triple.I1 >= Table.Length)
            {
                triple.I1 = -1;
            }
            if (triple.I2 >= Table.Length)
            {
                triple.I2 = -1;
            }
            //////end of hack


            bool singleMaterial = triple.I1 == -1 && triple.I2 == -1;

            if (singleMaterial)
            {
                size = sizeof(MyVoxelMaterialConstants);
                MyVoxelMaterialConstants constantsData = new MyVoxelMaterialConstants();
                constantsData.DistancesAndScale     = Table[triple.I0].DistanceAndScale;
                constantsData.DistancesAndScaleFar  = Table[triple.I0].DistanceAndScaleFar;
                constantsData.DistancesAndScaleFar3 = Table[triple.I0].DistanceAndScaleFar3;
                constantsData.Far3Color             = Table[triple.I0].Far3Color;
                constantsData.ExtensionDetailScale  = Table[triple.I0].ExtensionDetailScale;

                buffer = new byte[size];
                fixed(byte *dstPtr = buffer)
                {
                    MyMemory.CopyMemory(new IntPtr(dstPtr), new IntPtr(&constantsData), (uint)size);
                }
            }
            else
            {
                size = sizeof(MyVoxelMultiMaterialConstants);
                MyVoxelMultiMaterialConstants constantsData = new MyVoxelMultiMaterialConstants();

                constantsData.DistancesAndScale0    = Table[triple.I0].DistanceAndScale;
                constantsData.DistancesAndScale1    = Table[triple.I1].DistanceAndScale;
                constantsData.DistancesAndScale2    = triple.I2 >= 0 ? Table[triple.I2].DistanceAndScale : Vector4.Zero;
                constantsData.DistancesAndScaleFar0 = Table[triple.I0].DistanceAndScaleFar;
                constantsData.DistancesAndScaleFar1 = Table[triple.I1].DistanceAndScaleFar;
                constantsData.DistancesAndScaleFar2 = triple.I2 >= 0 ? Table[triple.I2].DistanceAndScaleFar : Vector4.Zero;
                constantsData.DistancesAndScaleFar3 = triple.I2 >= 0 ? Table[triple.I2].DistanceAndScaleFar3 : Vector2.Zero;
                constantsData.Far3Color             = triple.I2 >= 0 ? Table[triple.I2].Far3Color : Color.Black;
                constantsData.ExtensionDetailScale0 = Table[triple.I0].ExtensionDetailScale;
                constantsData.ExtensionDetailScale1 = Table[triple.I1].ExtensionDetailScale;
                constantsData.ExtensionDetailScale2 = triple.I2 >= 0 ? Table[triple.I2].ExtensionDetailScale : 0;

                buffer = new byte[size];
                fixed(byte *dstPtr = buffer)
                {
                    MyMemory.CopyMemory(new IntPtr(dstPtr), new IntPtr(&constantsData), (uint)size);
                }
            }

            var version = triple.I0.GetHashCode();

            MyHashHelper.Combine(ref version, triple.I1.GetHashCode());
            MyHashHelper.Combine(ref version, triple.I2.GetHashCode());

            return(new MyMaterialProxy_2
            {
                MaterialConstants =
                {
                    BindFlag = MyBindFlag.BIND_PS,
                    CB       = MyCommon.GetMaterialCB(size),
                    Version  = version,
                    Data     = buffer
                },
                MaterialSRVs =
                {
                    // NOTE(AF) Adding BIND_VS here will interfere with shadows, causing flickering in the first cascade
                    BindFlag  = MyBindFlag.BIND_PS,
                    StartSlot =                  0,
                    Version   = version,
                    SRVs      = singleMaterial
                            ?
                                new ShaderResourceView[]
                    {
                        Table[triple.I0].Near.ColorMetalArray.ShaderView, Table[triple.I0].Far1.ColorMetalArray.ShaderView, Table[triple.I0].Far2.ColorMetalArray.ShaderView,
                        Table[triple.I0].Near.NormalGlossArray.ShaderView, Table[triple.I0].Far1.NormalGlossArray.ShaderView, Table[triple.I0].Far2.NormalGlossArray.ShaderView,
                        Table[triple.I0].Near.ExtArray.ShaderView, Table[triple.I0].Far1.ExtArray.ShaderView, Table[triple.I0].Far2.ExtArray.ShaderView,
                    }
                            :
                    (
                        triple.I2 == -1
                                ?
                        new ShaderResourceView[]
                    {
                        Table[triple.I0].Near.ColorMetalArray.ShaderView, Table[triple.I0].Far1.ColorMetalArray.ShaderView, Table[triple.I0].Far2.ColorMetalArray.ShaderView,
                        Table[triple.I1].Near.ColorMetalArray.ShaderView, Table[triple.I1].Far1.ColorMetalArray.ShaderView, Table[triple.I1].Far2.ColorMetalArray.ShaderView,
                        null, null, null,
                        Table[triple.I0].Near.NormalGlossArray.ShaderView, Table[triple.I0].Far1.NormalGlossArray.ShaderView, Table[triple.I0].Far2.NormalGlossArray.ShaderView,
                        Table[triple.I1].Near.NormalGlossArray.ShaderView, Table[triple.I1].Far1.NormalGlossArray.ShaderView, Table[triple.I1].Far2.NormalGlossArray.ShaderView,
                        null, null, null,

                        Table[triple.I0].Near.ExtArray.ShaderView, Table[triple.I0].Far1.ExtArray.ShaderView, Table[triple.I0].Far2.ExtArray.ShaderView,
                        Table[triple.I1].Near.ExtArray.ShaderView, Table[triple.I1].Far1.ExtArray.ShaderView, Table[triple.I1].Far2.ExtArray.ShaderView,
                        null, null, null
                    }
                                :
                        new ShaderResourceView[]
                    {
                        Table[triple.I0].Near.ColorMetalArray.ShaderView, Table[triple.I0].Far1.ColorMetalArray.ShaderView, Table[triple.I0].Far2.ColorMetalArray.ShaderView,
                        Table[triple.I1].Near.ColorMetalArray.ShaderView, Table[triple.I1].Far1.ColorMetalArray.ShaderView, Table[triple.I1].Far2.ColorMetalArray.ShaderView,
                        Table[triple.I2].Near.ColorMetalArray.ShaderView, Table[triple.I2].Far1.ColorMetalArray.ShaderView, Table[triple.I2].Far2.ColorMetalArray.ShaderView,

                        Table[triple.I0].Near.NormalGlossArray.ShaderView, Table[triple.I0].Far1.NormalGlossArray.ShaderView, Table[triple.I0].Far2.NormalGlossArray.ShaderView,
                        Table[triple.I1].Near.NormalGlossArray.ShaderView, Table[triple.I1].Far1.NormalGlossArray.ShaderView, Table[triple.I1].Far2.NormalGlossArray.ShaderView,
                        Table[triple.I2].Near.NormalGlossArray.ShaderView, Table[triple.I2].Far1.NormalGlossArray.ShaderView, Table[triple.I2].Far2.NormalGlossArray.ShaderView,

                        Table[triple.I0].Near.ExtArray.ShaderView, Table[triple.I0].Far1.ExtArray.ShaderView, Table[triple.I0].Far2.ExtArray.ShaderView,
                        Table[triple.I1].Near.ExtArray.ShaderView, Table[triple.I1].Far1.ExtArray.ShaderView, Table[triple.I1].Far2.ExtArray.ShaderView,
                        Table[triple.I2].Near.ExtArray.ShaderView, Table[triple.I2].Far1.ExtArray.ShaderView, Table[triple.I2].Far2.ExtArray.ShaderView,
                    }
                    )
                }
            });
        }
        internal static MyBindableResource Run(MyBindableResource uav0, MyBindableResource uav1, MyBindableResource src,
                                               MyBindableResource prevLum)
        {
            var   size             = src.GetSize();
            var   texelsNum        = size.X * size.Y;
            uint  sizeX            = (uint)size.X;
            uint  sizeY            = (uint)size.Y;
            float adaptationFactor = MyRender11.Postprocess.EnableEyeAdaptation ? -1.0f : MyRender11.Postprocess.ConstantLuminance;
            var   buffer           = MyCommon.GetObjectCB(16);
            var   mapping          = MyMapping.MapDiscard(buffer);

            mapping.WriteAndPosition(ref sizeX);
            mapping.WriteAndPosition(ref sizeY);
            mapping.WriteAndPosition(ref texelsNum);
            mapping.WriteAndPosition(ref adaptationFactor);
            mapping.Unmap();

            RC.CSSetCB(0, MyCommon.FrameConstants);
            RC.CSSetCB(1, MyCommon.GetObjectCB(16));

            RC.BindUAV(0, uav0);
            RC.BindSRV(0, src);
            RC.SetCS(m_initialShader);

            RC.DeviceContext.Dispatch((size.X + m_numthreads - 1) / m_numthreads, (size.Y + m_numthreads - 1) / m_numthreads, 1);

            RC.SetCS(m_sumShader);
            int i = 0;

            while (true)
            {
                size.X = (size.X + m_numthreads - 1) / m_numthreads;
                size.Y = (size.Y + m_numthreads - 1) / m_numthreads;

                if (size.X <= 8 && size.Y <= 8)
                {
                    break;
                }

                //mapping = MyMapping.MapDiscard(MyCommon.GetObjectBuffer(16).Buffer);
                //mapping.stream.Write(new Vector2I(size.X, size.Y));
                //mapping.Unmap();

                RC.BindUAV(0, (i % 2 == 0) ? uav1 : uav0);
                RC.BindSRV(0, (i % 2 == 0) ? uav0 : uav1);

                RC.DeviceContext.Dispatch((size.X + m_numthreads - 1) / m_numthreads, (size.Y + m_numthreads - 1) / m_numthreads, 1);

                //might not be exactly correct if we skip this
                var dirty = (i % 2 == 0) ? uav0 : uav1;
                RC.DeviceContext.ClearUnorderedAccessView((dirty as IUnorderedAccessBindable).UAV, new SharpDX.Int4(0, 0, 0, 0));

                i++;
            }

            RC.SetCS(m_finalShader);

            //mapping = MyMapping.MapDiscard(MyCommon.GetObjectBuffer(16).Buffer);
            //mapping.stream.Write(new Vector2I(size.X, size.Y));
            //mapping.stream.Write(texelsNum);
            //mapping.Unmap();

            RC.BindUAV(0, (i % 2 == 0) ? uav1 : uav0);
            RC.BindSRVs(0, (i % 2 == 0) ? uav0 : uav1, prevLum);

            RC.DeviceContext.Dispatch((size.X + m_numthreads - 1) / m_numthreads, (size.Y + m_numthreads - 1) / m_numthreads, 1);

            RC.SetCS(null);

            var output = (i % 2 == 0) ? uav1 : uav0;

            RC.DeviceContext.CopySubresourceRegion(output.m_resource, 0, new ResourceRegion(0, 0, 0, 1, 1, 1), prevLum.m_resource, 0);

            return(output);
        }
Пример #6
0
        internal unsafe static void RenderSpotlights()
        {
            RC.BindDepthRT(MyGBuffer.Main.Get(MyGbufferSlot.DepthStencil), DepthStencilAccess.ReadOnly, MyGBuffer.Main.Get(MyGbufferSlot.LBuffer));
            RC.DeviceContext.Rasterizer.SetViewport(0, 0, MyRender11.ViewportResolution.X, MyRender11.ViewportResolution.Y);
            RC.DeviceContext.InputAssembler.PrimitiveTopology = SharpDX.Direct3D.PrimitiveTopology.TriangleList;

            var coneMesh = MyMeshes.GetMeshId(X.TEXT_("Models/Debug/Cone.mwm"));
            var buffers  = MyMeshes.GetLodMesh(coneMesh, 0).Buffers;

            RC.SetVB(0, buffers.VB0.Buffer, buffers.VB0.Stride);
            RC.SetIB(buffers.IB.Buffer, buffers.IB.Format);

            RC.SetVS(SpotlightProxyVs);
            RC.SetIL(SpotlightProxyIL);

            RC.SetRS(MyRender11.m_invTriRasterizerState);

            var cb = MyCommon.GetObjectCB(sizeof(SpotlightConstants));

            RC.SetCB(1, cb);
            RC.DeviceContext.PixelShader.SetSampler(13, SamplerStates.m_alphamask);
            RC.DeviceContext.PixelShader.SetSampler(14, SamplerStates.m_shadowmap);
            RC.DeviceContext.PixelShader.SetSampler(15, SamplerStates.m_shadowmap);

            int index       = 0;
            int casterIndex = 0;

            foreach (var id in VisibleSpotlights)
            {
                MyLights.WriteSpotlightConstants(id, ref Spotlights[index]);

                var mapping = MyMapping.MapDiscard(cb);
                mapping.WriteAndPosition(ref Spotlights[index]);
                mapping.Unmap();

                RC.DeviceContext.PixelShader.SetShaderResource(13, MyTextures.GetView(MyLights.Spotlights[id.Index].ReflectorTexture));

                if (id.CastsShadowsThisFrame)
                {
                    RC.DeviceContext.PixelShader.SetShaderResource(14, MyRender11.DynamicShadows.ShadowmapsPool[casterIndex].SRV);
                    casterIndex++;
                }

                RC.SetPS(SpotlightPs_Pixel);
                if (MyRender11.MultisamplingEnabled)
                {
                    RC.SetDS(MyDepthStencilState.TestEdgeStencil, 0);
                }
                RC.DeviceContext.DrawIndexed(MyMeshes.GetLodMesh(coneMesh, 0).Info.IndicesNum, 0, 0);

                if (MyRender11.MultisamplingEnabled)
                {
                    RC.SetPS(SpotlightPs_Sample);
                    RC.SetDS(MyDepthStencilState.TestEdgeStencil, 0x80);
                    RC.DeviceContext.DrawIndexed(MyMeshes.GetLodMesh(coneMesh, 0).Info.IndicesNum, 0, 0);
                }

                index++;
                if (index >= SPOTLIGHTS_MAX)
                {
                    break;
                }
            }

            if (MyRender11.MultisamplingEnabled)
            {
                RC.SetDS(MyDepthStencilState.DefaultDepthState);
            }

            RC.SetRS(null);
        }
Пример #7
0
        static unsafe MyMaterialProxy_2 CreateProxy(MyVoxelMaterialTriple triple)
        {
            byte[] buffer;
            int    size;
            bool   singleMaterial = triple.I1 == -1 && triple.I2 == -1;

            if (singleMaterial)
            {
                size = sizeof(MyVoxelMaterialConstants);
                MyVoxelMaterialConstants constantsData = new MyVoxelMaterialConstants();
                constantsData.Scales = Table[triple.I0].ScaleFactors;
                buffer = new byte[size];
                fixed(byte *dstPtr = buffer)
                {
                    MyMemory.CopyMemory(new IntPtr(dstPtr), new IntPtr(&constantsData), (uint)size);
                }
            }
            else
            {
                size = sizeof(MyVoxelMultiMaterialConstants);
                MyVoxelMultiMaterialConstants constantsData = new MyVoxelMultiMaterialConstants();

                constantsData.Scales0 = Table[triple.I0].ScaleFactors;
                constantsData.Scales1 = Table[triple.I1].ScaleFactors;
                constantsData.Scales2 = triple.I2 >= 0 ? Table[triple.I2].ScaleFactors : Vector3.One;
                buffer = new byte[size];
                fixed(byte *dstPtr = buffer)
                {
                    MyMemory.CopyMemory(new IntPtr(dstPtr), new IntPtr(&constantsData), (uint)size);
                }
            }

            var version = triple.I0.GetHashCode();

            MyHashHelper.Combine(ref version, triple.I1.GetHashCode());
            MyHashHelper.Combine(ref version, triple.I2.GetHashCode());

            return(new MyMaterialProxy_2
            {
                MaterialConstants =
                {
                    BindFlag = MyBindFlag.BIND_PS,
                    CB       = MyCommon.GetMaterialCB(size),
                    Version  = version,
                    Data     = buffer
                },
                MaterialSRVs =
                {
                    BindFlag  = MyBindFlag.BIND_PS,
                    StartSlot =                  0,
                    Version   = version,
                    SRVs      = singleMaterial
                            ?
                                new ShaderResourceView[]
                    {
                        Table[triple.I0].Near.ColorMetalArray.ShaderView, Table[triple.I0].Far1.ColorMetalArray.ShaderView, Table[triple.I0].Far2.ColorMetalArray.ShaderView,
                        Table[triple.I0].Near.NormalGlossArray.ShaderView, Table[triple.I0].Far1.NormalGlossArray.ShaderView, Table[triple.I0].Far2.NormalGlossArray.ShaderView,
                    }
                            :
                    (
                        triple.I2 == -1
                                ?
                        new ShaderResourceView[]
                    {
                        Table[triple.I0].Near.ColorMetalArray.ShaderView, Table[triple.I0].Far1.ColorMetalArray.ShaderView, Table[triple.I0].Far2.ColorMetalArray.ShaderView,
                        Table[triple.I1].Near.ColorMetalArray.ShaderView, Table[triple.I1].Far1.ColorMetalArray.ShaderView, Table[triple.I1].Far2.ColorMetalArray.ShaderView,
                        null, null, null,
                        Table[triple.I0].Near.NormalGlossArray.ShaderView, Table[triple.I0].Far1.NormalGlossArray.ShaderView, Table[triple.I0].Far2.NormalGlossArray.ShaderView,
                        Table[triple.I1].Near.NormalGlossArray.ShaderView, Table[triple.I1].Far1.NormalGlossArray.ShaderView, Table[triple.I1].Far2.NormalGlossArray.ShaderView,
                        null, null, null,

                        null, null, null,
                        null, null, null,
                        null, null, null
                    }
                                :
                        new ShaderResourceView[]
                    {
                        Table[triple.I0].Near.ColorMetalArray.ShaderView, Table[triple.I0].Far1.ColorMetalArray.ShaderView, Table[triple.I0].Far2.ColorMetalArray.ShaderView,
                        Table[triple.I1].Near.ColorMetalArray.ShaderView, Table[triple.I1].Far1.ColorMetalArray.ShaderView, Table[triple.I1].Far2.ColorMetalArray.ShaderView,
                        Table[triple.I2].Near.ColorMetalArray.ShaderView, Table[triple.I2].Far1.ColorMetalArray.ShaderView, Table[triple.I2].Far2.ColorMetalArray.ShaderView,

                        Table[triple.I0].Near.NormalGlossArray.ShaderView, Table[triple.I0].Far1.NormalGlossArray.ShaderView, Table[triple.I0].Far2.NormalGlossArray.ShaderView,
                        Table[triple.I1].Near.NormalGlossArray.ShaderView, Table[triple.I1].Far1.NormalGlossArray.ShaderView, Table[triple.I1].Far2.NormalGlossArray.ShaderView,
                        Table[triple.I2].Near.NormalGlossArray.ShaderView, Table[triple.I2].Far1.NormalGlossArray.ShaderView, Table[triple.I2].Far2.NormalGlossArray.ShaderView,

                        null, null, null,
                        null, null, null,
                        null, null, null
                    }
                    )
                }
            });
        }
Пример #8
0
        internal unsafe static void Render(MyBindableResource dst, MyBindableResource depth, MyBindableResource depthRead)
        {
            if (!MyRender11.DebugOverrides.BillboardsDynamic)
            {
                OnFrameStart();
            }

            m_stats.Clear();
            MyRender11.GetRenderProfiler().StartProfilingBlock("Gather");
            Gather();
            MyRender11.GetRenderProfiler().EndProfilingBlock();

            MyRender11.GetRenderProfiler().StartProfilingBlock("Draw");
            TransferData();

            RC.SetupScreenViewport();
            RC.BindDepthRT(depth, DepthStencilAccess.ReadOnly, dst);
            RC.SetBS(MyRender11.BlendAlphaPremult);
            RC.SetRS(MyRender11.m_nocullRasterizerState);
            RC.BindRawSRV(104, m_SB);
            RC.BindSRV(1, depthRead);
            RC.SetCB(2, MyCommon.GetObjectCB(sizeof(Matrix) * MaxCustomProjections));
            RC.SetDS(MyDepthStencilState.DefaultDepthState);

            RC.SetCB(4, MyRender11.DynamicShadows.ShadowCascades.CascadeConstantBuffer);
            RC.DeviceContext.VertexShader.SetSampler(MyCommon.SHADOW_SAMPLER_SLOT, SamplerStates.m_shadowmap);
            RC.DeviceContext.VertexShader.SetShaderResource(MyCommon.CASCADES_SM_SLOT, MyRender11.DynamicShadows.ShadowCascades.CascadeShadowmapArray.SRV);
            RC.DeviceContext.VertexShader.SetSamplers(0, SamplerStates.StandardSamplers);

            RC.DeviceContext.VertexShader.SetShaderResource(MyCommon.SKYBOX_IBL_SLOT,
                                                            MyRender11.IsIntelBrokenCubemapsWorkaround ? MyTextures.GetView(MyTextures.IntelFallbackCubeTexId) : MyEnvironmentProbe.Instance.cubemapPrefiltered.SRV);
            RC.DeviceContext.VertexShader.SetShaderResource(MyCommon.SKYBOX2_IBL_SLOT,
                                                            MyTextures.GetView(MyTextures.GetTexture(MyEnvironment.NightSkyboxPrefiltered, MyTextureEnum.CUBEMAP, true)));

            RC.SetVB(0, m_VB.Buffer, m_VB.Stride);
            RC.SetIB(m_IB.Buffer, m_IB.Format);

            RC.SetIL(m_inputLayout);

            for (int i = 0; i < m_batches.Count; i++)
            {
                // first part of batches contain sorted billboards and they read depth
                // second part of batches contain unsorted billboards and they ignore depth
                // switch here:
                if (m_batches[i].Offset == m_sortedBillboardsNum)
                {
                    //RC.BindDepthRT(null, DepthStencilAccess.ReadOnly, dst);
                }

                if (m_batches[i].Lit)
                {
                    RC.SetVS(m_vsLit);

                    if (m_batches[i].AlphaCutout)
                    {
                        RC.SetPS(m_psAlphaCutoutAndLit);
                    }
                    else
                    {
                        RC.SetPS(m_psLit);
                    }
                }
                else
                if (m_batches[i].AlphaCutout)
                {
                    RC.SetVS(m_vs);
                    RC.SetPS(m_psAlphaCutout);
                }
                else
                {
                    RC.SetVS(m_vs);
                    RC.SetPS(m_ps);
                }

                RC.BindRawSRV(0, m_batches[i].Texture);
                RC.DeviceContext.DrawIndexed(m_batches[i].Num * 6, m_batches[i].Offset * 6, 0);
                ++RC.Stats.BillboardDrawIndexed;
            }
            m_stats.Billboards += m_sorted + m_unsorted;

            RC.SetRS(null);
            RC.SetBS(null);
            m_batches.Clear();
            MyRender11.GatherStats(m_stats);
            MyRender11.GetRenderProfiler().EndProfilingBlock();
        }
Пример #9
0
        internal static int Gather(MyGPUEmitterData[] data, out SharpDX.Direct3D11.ShaderResourceView textureArraySRV)
        {
            for (int i = 0; i < MAX_LIVE_EMITTERS; i++)
            {
                data[i].NumParticlesToEmitThisFrame = 0;
            }

            // sort emitters!
            List <MyLiveData> emitters = m_emitters.Values.ToList();

            //if (emitters.Count > MAX_LIVE_EMITTERS)
            emitters.Sort();

            int  maxEmitterIndex        = -1;
            uint textureIndex           = 0;
            int  unassociatedCount      = 0;
            int  skipCount              = 0;
            int  unsortedCount          = 0;
            int  firstUnassociatedIndex = -1;
            int  lastAssociatedIndex    = -1;

            for (int i = 0; i < emitters.Count; i++)
            {
                var emitter = emitters[i];
                // assiociate buffer index to new emitters & track overload to free space for unassociated near emitters later
                if (emitter.BufferIndex == -1)
                {
                    if (m_freeBufferIndices.Count > 0)
                    {
                        emitter.BufferIndex = m_freeBufferIndices.Pop();
                    }
                    else
                    {
                        unassociatedCount++;
                        if (firstUnassociatedIndex == -1)
                        {
                            firstUnassociatedIndex = i;
                        }
                    }
                }
                else
                {
                    skipCount           = unassociatedCount;
                    lastAssociatedIndex = i;
                    if (unassociatedCount > 0)
                    {
                        unsortedCount++;
                    }
                }

                if (MyCommon.TimerMs > emitter.DieAt)
                {
                    emitter.GPUEmitter.Data.Flags |= GPUEmitterFlags.Dead;
                }

                if (emitter.BufferIndex != -1)
                {
                    if ((emitter.GPUEmitter.Data.Flags & GPUEmitterFlags.FreezeEmit) == 0)
                    {
                        float toEmit = MyCommon.LastFrameDelta() * emitter.GPUEmitter.ParticlesPerSecond +
                                       emitter.ParticlesEmittedFraction;
                        emitter.GPUEmitter.Data.NumParticlesToEmitThisFrame = (int)toEmit;
                        emitter.ParticlesEmittedFraction = toEmit - emitter.GPUEmitter.Data.NumParticlesToEmitThisFrame;
                    }

                    if (emitter.TextureId != Resources.TexId.NULL)
                    {
                        MyRenderProxy.Assert(m_textureArrayIndices.ContainsKey(emitter.TextureId));
                        textureIndex = m_textureArrayIndices[emitter.TextureId].Index;
                    }
                    else
                    {
                        textureIndex = 0;
                    }

                    int bufferIndex = emitter.BufferIndex;
                    data[bufferIndex] = emitter.GPUEmitter.Data;
                    Vector3 pos = emitter.GPUEmitter.WorldPosition - MyRender11.Environment.CameraPosition;
                    data[bufferIndex].RotationMatrix.M14 = pos.X;
                    data[bufferIndex].RotationMatrix.M24 = pos.Y;
                    data[bufferIndex].RotationMatrix.M34 = pos.Z;
                    data[bufferIndex].TextureIndex1     |= textureIndex << (ATLAS_INDEX_BITS + ATLAS_DIMENSION_BITS * 2);

                    if (bufferIndex > maxEmitterIndex)
                    {
                        maxEmitterIndex = bufferIndex;
                    }
                }
            }

            /*MyRenderStats.Generic.WriteFormat("GPU particles allocated: {0}", totalParticles, VRage.Stats.MyStatTypeEnum.CurrentValue, 300, 0);
             * MyRenderStats.Generic.WriteFormat("GPU particles overload: {0}", overloadedParticles ? 1.0f : 0, VRage.Stats.MyStatTypeEnum.CurrentValue, 300, 0);
             * MyRenderStats.Generic.WriteFormat("GPU emitters overload: {0}", overloadedEmitters ? 1.0f : 0, VRage.Stats.MyStatTypeEnum.CurrentValue, 300, 0);*/

            UpdateTextureArray();
            if (m_textureArray != null)
            {
                textureArraySRV = m_textureArray.SRV;
            }
            else
            {
                textureArraySRV = null;
            }

            // stop emitters far away to make room for emitters nearby
            if (skipCount > 0 && unsortedCount > 0)
            {
                // iterate until buffer-unassociated index is larger then unassocited one
                for (int i = firstUnassociatedIndex, j = lastAssociatedIndex; i < j;)
                {
                    var emitter = emitters[j];
                    // free last buffer-associated emitter
                    data[emitter.BufferIndex].Flags |= GPUEmitterFlags.Dead;
                    data[emitter.BufferIndex].NumParticlesToEmitThisFrame = 0;
                    m_freeBufferIndices.Push(emitter.BufferIndex);
                    emitter.BufferIndex = -1;

                    // find new last buffer-associated emitter
                    do
                    {
                        j--;
                    }while (j > 0 && emitters[j].BufferIndex == -1);

                    // find next buffer-unassociated emitter
                    do
                    {
                        i++;
                    } while (i < emitters.Count && emitters[i].BufferIndex != -1);
                }
            }

            foreach (var emitter in emitters)
            {
                if ((emitter.GPUEmitter.Data.Flags & GPUEmitterFlags.Dead) > 0)
                {
                    Remove(emitter);
                }
            }

            return(maxEmitterIndex + 1);
        }
Пример #10
0
        internal unsafe static void Render(MyBindableResource dst, MyBindableResource depth, MyBindableResource depthRead)
        {
            MyRender11.GetRenderProfiler().StartProfilingBlock("Gather");
            Gather();
            MyRender11.GetRenderProfiler().EndProfilingBlock();


            MyRender11.GetRenderProfiler().StartProfilingBlock("Draw");
            TransferData();

            RC.SetupScreenViewport();
            RC.BindDepthRT(depth, DepthStencilAccess.ReadOnly, dst);
            RC.SetBS(MyRender11.BlendAlphaPremult);
            RC.SetRS(MyRender11.m_nocullRasterizerState);
            RC.BindRawSRV(104, m_SB.Srv);
            RC.BindSRV(1, depthRead);
            RC.SetCB(2, MyCommon.GetObjectCB(sizeof(Matrix) * MaxCustomProjections));
            RC.SetDS(MyDepthStencilState.DefaultDepthState);

            RC.SetCB(4, MyShadows.m_csmConstants);
            RC.Context.VertexShader.SetSampler(MyCommon.SHADOW_SAMPLER_SLOT, MyRender11.m_shadowmapSamplerState);
            RC.Context.VertexShader.SetShaderResource(MyCommon.CASCADES_SM_SLOT, MyShadows.m_cascadeShadowmapArray.ShaderView);
            RC.Context.VertexShader.SetSamplers(0, MyRender11.StandardSamplers);


            RC.Context.VertexShader.SetShaderResource(MyCommon.SKYBOX_IBL_SLOT, MyTextures.GetView(MyTextures.GetTexture(MyEnvironment.DaySkyboxPrefiltered, MyTextureEnum.CUBEMAP, true)));
            RC.Context.PixelShader.SetShaderResource(MyCommon.SKYBOX2_IBL_SLOT, MyTextures.GetView(MyTextures.GetTexture(MyEnvironment.NightSkyboxPrefiltered, MyTextureEnum.CUBEMAP, true)));

            RC.SetVB(0, m_VB.Buffer, m_VB.Stride);
            RC.SetIB(m_IB.Buffer, m_IB.Format);

            RC.SetIL(m_inputLayout);

            for (int i = 0; i < m_batches.Count; i++)
            {
                // first part of batches contain sorted billboards and they read depth
                // second part of batches contain unsorted billboards and they ignore depth
                // switch here:
                if (m_batches[i].Offset == m_sortedBillboardsNum)
                {
                    //RC.BindDepthRT(null, DepthStencilAccess.ReadOnly, dst);
                }

                if (m_batches[i].Lit)
                {
                    RC.SetVS(m_vsLit);
                    RC.SetPS(m_psLit);
                }
                else
                {
                    RC.SetVS(m_vs);
                    RC.SetPS(m_ps);
                }

                RC.BindRawSRV(0, m_batches[i].Texture);
                RC.Context.DrawIndexed(m_batches[i].Num * 6, m_batches[i].Offset * 6, 0);
            }

            RC.SetRS(null);
            m_batches.Clear();
            MyRender11.GetRenderProfiler().EndProfilingBlock();
        }
Пример #11
0
        // can be on another job
        internal unsafe static void Draw()
        {
            var decals = IdIndex.Values.ToArray();

            // sort visible decals by material
            Array.Sort(decals, DecalsMaterialComparer);

            ///
            // copy gbuffer with normals for read (uhoh)
            // bind copy and depth for read
            // bind gbuffer for write

            var RC = MyImmediateRC.RC;

            RC.DeviceContext.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
            RC.SetIB(m_IB.Buffer, m_IB.Format);
            RC.SetIL(null);
            RC.DeviceContext.Rasterizer.SetViewport(0, 0, MyRender11.ViewportResolution.X, MyRender11.ViewportResolution.Y);
            RC.SetCB(MyCommon.FRAME_SLOT, MyCommon.FrameConstants);
            RC.BindGBufferForWrite(MyGBuffer.Main, DepthStencilAccess.DepthReadOnly);
            RC.SetVS(m_vs);
            RC.SetPS(m_ps);
            RC.SetDS(MyDepthStencilState.DepthTest);
            RC.DeviceContext.PixelShader.SetSamplers(0, MyRender11.StandardSamplers);

            RC.BindSRV(0, MyGBuffer.Main.DepthStencil.Depth);
            RC.DeviceContext.PixelShader.SetShaderResource(1, MyRender11.m_gbuffer1Copy.ShaderView);

            var decalCb = MyCommon.GetObjectCB(sizeof(MyDecalConstants) * MAX_DECALS);

            RC.SetCB(2, decalCb);

            var prevMaterial            = new MyStringId();
            MyScreenDecalType decalType = MyScreenDecalType.ScreenDecalBump;

            for (int i = 0; i < decals.Length; ++i)
            {
                var index = decals[i];

                var material = Decals.Data[index].Material;
                if (i == 0 || material != prevMaterial)
                {
                    DrawBatch(decalType);

                    var matDesc = Materials[material];

                    decalType = matDesc.DecalType;
                    // factor 1 makes overwriting of gbuffer color & subtracting from ao
                    RC.SetBS(MyRender11.BlendDecal, matDesc.DecalType == MyScreenDecalType.ScreenDecalBump ? new SharpDX.Color4(0) : SharpDX.Color4.White);
                    RC.DeviceContext.PixelShader.SetShaderResource(3, MyTextures.GetView(matDesc.AlphamaskTexture));
                    RC.DeviceContext.PixelShader.SetShaderResource(4, MyTextures.GetView(matDesc.ColorMetalTexture));
                    RC.DeviceContext.PixelShader.SetShaderResource(5, MyTextures.GetView(matDesc.NormalmapTexture));
                }

                var parent = MyIDTracker <MyActor> .FindByID(Decals.Data[index].ParentID);

                if (parent != null)
                {
                    var parentMatrix = parent.WorldMatrix;
                    var volumeMatrix = Decals.Data[index].LocalOBB * parentMatrix * Matrix.CreateTranslation(-MyEnvironment.CameraPosition);

                    m_matrices.Add(volumeMatrix);
                }
            }
            DrawBatch(decalType);

            RC.SetBS(null);
        }
Пример #12
0
        internal static void PreparePointLights()
        {
            var activePointlights = 0;

            MyLights.Update();
            BoundingFrustumD viewFrustumClippedD = MyRender11.Environment.ViewFrustumClippedD;

            if (MyStereoRender.Enable)
            {
                if (MyStereoRender.RenderRegion == MyStereoRegion.LEFT)
                {
                    viewFrustumClippedD = MyStereoRender.EnvMatricesLeftEye.ViewFrustumClippedD;
                }
                else if (MyStereoRender.RenderRegion == MyStereoRegion.RIGHT)
                {
                    viewFrustumClippedD = MyStereoRender.EnvMatricesRightEye.ViewFrustumClippedD;
                }
            }
            MyLights.PointlightsBvh.OverlapAllFrustum(ref viewFrustumClippedD, VisiblePointlights);

            bool visiblePointlights = VisiblePointlights.Count != 0;

            if (!visiblePointlights && !m_lastFrameVisiblePointlights)
            {
                return;
            }

            m_lastFrameVisiblePointlights = visiblePointlights;

            if (VisiblePointlights.Count > MyRender11Constants.MAX_POINT_LIGHTS)
            {
                VisiblePointlights.Sort((x, y) => x.ViewerDistanceSquared.CompareTo(y.ViewerDistanceSquared));

                while (VisiblePointlights.Count > MyRender11Constants.MAX_POINT_LIGHTS)
                {
                    VisiblePointlights.RemoveAtFast(VisiblePointlights.Count - 1);
                }
            }

            foreach (var light in VisiblePointlights)
            {
                MyLights.WritePointlightConstants(light, ref m_pointlightsCullBuffer[activePointlights]);

                activePointlights++;
                Debug.Assert(activePointlights <= MyRender11Constants.MAX_POINT_LIGHTS);
            }
            for (int lightIndex = activePointlights; lightIndex < MyRender11Constants.MAX_POINT_LIGHTS; ++lightIndex)
            {
                MyLights.WritePointlightConstants(LightId.NULL, ref m_pointlightsCullBuffer[lightIndex]);
            }

            var mapping = MyMapping.MapDiscard(MyCommon.GetObjectCB(16));

            mapping.WriteAndPosition(ref activePointlights);
            mapping.Unmap();

            mapping = MyMapping.MapDiscard(m_pointlightCullHwBuffer.Buffer);
            mapping.WriteAndPosition(m_pointlightsCullBuffer, 0, MyRender11Constants.MAX_POINT_LIGHTS);
            mapping.Unmap();

            if (!MyStereoRender.Enable)
            {
                RC.CSSetCB(0, MyCommon.FrameConstants);
            }
            else
            {
                MyStereoRender.CSBindRawCB_FrameConstants(RC);
            }
            RC.CSSetCB(1, MyCommon.GetObjectCB(16));

            //RC.BindUAV(0, MyScreenDependants.m_test);
            RC.BindUAV(0, MyScreenDependants.m_tileIndices);
            RC.BindGBufferForRead(0, MyGBuffer.Main);
            RC.CSBindRawSRV(MyCommon.POINTLIGHT_SLOT, m_pointlightCullHwBuffer);
            RC.SetCS(m_preparePointLights);
            Vector2I tiles = new Vector2I(MyScreenDependants.TilesX, MyScreenDependants.TilesY);

            if (MyStereoRender.Enable && MyStereoRender.RenderRegion != MyStereoRegion.FULLSCREEN)
            {
                tiles.X /= 2;
            }

            RC.DeviceContext.Dispatch(tiles.X, tiles.Y, 1);
            RC.SetCS(null);
        }
Пример #13
0
        internal static IBorrowedUavTexture Run(ISrvBindable src)
        {
            IBorrowedUavTexture uav0 = MyManagers.RwTexturesPool.BorrowUav("MyLuminanceAverage.Uav0", Format.R32G32_Float);
            IBorrowedUavTexture uav1 = MyManagers.RwTexturesPool.BorrowUav("MyLuminanceAverage.Uav1", Format.R32G32_Float);

            Vector2I size      = src.Size;
            int      texelsNum = size.X * size.Y;
            uint     sizeX     = (uint)size.X;
            uint     sizeY     = (uint)size.Y;
            var      buffer    = MyCommon.GetObjectCB(16);
            var      mapping   = MyMapping.MapDiscard(buffer);

            mapping.WriteAndPosition(ref sizeX);
            mapping.WriteAndPosition(ref sizeY);
            mapping.WriteAndPosition(ref texelsNum);
            mapping.Unmap();

            RC.ComputeShader.SetConstantBuffer(MyCommon.FRAME_SLOT, MyCommon.FrameConstants);
            RC.ComputeShader.SetConstantBuffer(1, MyCommon.GetObjectCB(16));

            RC.ComputeShader.Set(m_initialShader);

            IBorrowedUavTexture output   = uav0;
            ISrvBindable        inputSrc = src;

            RC.ComputeShader.SetUav(0, output);
            RC.ComputeShader.SetSrv(0, inputSrc);

            int threadGroupCountX = ComputeGroupCount(size.X);
            int threadGroupCountY = ComputeGroupCount(size.Y);

            RC.Dispatch(threadGroupCountX, threadGroupCountY, 1);
            RC.ComputeShader.Set(m_sumShader);

            IBorrowedUavTexture input;
            int i = 0;

            while (true)
            {
                size.X = threadGroupCountX;
                size.Y = threadGroupCountY;

                if (size.X <= NUM_THREADS && size.Y <= NUM_THREADS)
                {
                    break;
                }

                output = (i % 2 == 0) ? uav1 : uav0;
                input  = (i % 2 == 0) ? uav0 : uav1;

                RC.ComputeShader.SetSrv(0, null);
                RC.ComputeShader.SetUav(0, output);
                RC.ComputeShader.SetSrv(0, input);

                threadGroupCountX = ComputeGroupCount(size.X);
                threadGroupCountY = ComputeGroupCount(size.Y);
                RC.Dispatch(threadGroupCountX, threadGroupCountY, 1);

                i++;
            }

            RC.ComputeShader.Set(m_finalShader);

            output = (i % 2 == 0) ? uav1 : uav0;
            input  = (i % 2 == 0) ? uav0 : uav1;

            RC.ComputeShader.SetSrv(0, null);
            RC.ComputeShader.SetUav(0, output);
            RC.ComputeShader.SetSrvs(0, input, m_prevLum);

            threadGroupCountX = ComputeGroupCount(size.X);
            threadGroupCountY = ComputeGroupCount(size.Y);
            RC.Dispatch(threadGroupCountX, threadGroupCountY, 1);

            RC.ComputeShader.Set(null);
            RC.ComputeShader.SetUav(0, null);

            // Backup the result for later process
            RC.CopySubresourceRegion(output, 0, new ResourceRegion(0, 0, 0, 1, 1, 1), m_prevLum, 0);

            input.Release();
            return(output);
        }