Reducing State Changes when Calling Direct3D Effects

Started by
0 comments, last by StarBP 14 years, 10 months ago
I was working on a system to use a genetic algorithm to compress images using the GPU, and I am proud to announce that IT IS FINISHED!!! (well, at least the alpha version is; there is still no file format for it) It gets around 1,200 generations per second on a GeForce 8600 GT. The only problem is that it is severely limited by the state changes which occur during every pass of the sum reduction algorithm at the Effect.BeginPass(0) and Effect.EndPass() calls. More than half of these state changes are blatantly unnecessary (PIX says that all texture samplers, even those that aren't even used in the passes involved, are being set as part of each BeginPass call). The source can be found at http://tinyurl.com/mvothv (There is a binary in the bin/Release folder). It is released under the General Public License, simply meaning that all applications utilizing any part of this source code must reveal their source code, as well. I may change this licensing restriction at a later date, but the GPL version will always be the only free version. This program is based on Roger Alsing's original SLOW EvoLisa program (a fast, source-only version of it [still in GDI+, thus much slower than even my existing Direct3D version] can be found at http://starcalc.110mb.com/EvoLisa.zip). [Edited by - StarBP on June 22, 2009 8:39:46 AM]
Advertisement
Here is the specific section of the source that has all the state changes (you can download the full source from the TinyURL link in the first post):
                        if (activeLogHeight > 1 && activeLogWidth > 1 && activeLogWidth * activeLogHeight > 512)                        {                            fitnessRenderToSurface2.BeginScene(fitnessSurface2);                            device.VertexFormat = CustomVertex.PositionTextured.Format;                            device.SetStreamSource(0, fitnessVBHalf, 0);                            device.VertexDeclaration = fitnessVertexDeclaration;                            fitnessEffect.Technique = "VersionOneOtherParts";                            fitnessEffect.SetValue("TextureOne", fitnessTexture1);                            fitnessEffect.SetValue("FitnessMatrix", fitnessMatrix);                            fitnessEffect.SetValue("xOffset", (float)(0.5 / (double)logWidth));                            fitnessEffect.SetValue("yOffset", (float)(0.5 / (double)logHeight));                            fitnessEffect.Begin(0);                            fitnessEffect.BeginPass(0);                            device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);                            fitnessEffect.EndPass();                            fitnessEffect.End();                            fitnessRenderToSurface2.EndScene(Filter.None);                            activeLogHeight /= 2;                            activeLogWidth /= 2;                        }                        #region Some more ping-ponging back and forth for the reduction                        if (activeLogHeight > 1 && activeLogWidth > 1 && activeLogWidth * activeLogHeight > 512)                        {                            fitnessRenderToSurface1.BeginScene(fitnessSurface1);                            device.VertexFormat = CustomVertex.PositionTextured.Format;                            device.SetStreamSource(0, fitnessVBFourth, 0);                            device.VertexDeclaration = fitnessVertexDeclaration;                            fitnessEffect.Technique = "VersionOneOtherParts";                            fitnessEffect.SetValue("TextureOne", fitnessTexture2);                            fitnessEffect.SetValue("FitnessMatrix", fitnessMatrix);                            fitnessEffect.SetValue("xOffset", (float)(0.5 / (double)logWidth));                            fitnessEffect.SetValue("yOffset", (float)(0.5 / (double)logHeight));                            fitnessEffect.Begin(0);                            fitnessEffect.BeginPass(0);                            device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);                            fitnessEffect.EndPass();                            fitnessEffect.End();                            fitnessRenderToSurface1.EndScene(Filter.None);                            activeLogHeight /= 2;                            activeLogWidth /= 2;                        }                        if (activeLogHeight > 1 && activeLogWidth > 1 && activeLogWidth * activeLogHeight > 512)                        {                            fitnessRenderToSurface2.BeginScene(fitnessSurface2);                            device.VertexFormat = CustomVertex.PositionTextured.Format;                            device.SetStreamSource(0, fitnessVBEighth, 0);                            device.VertexDeclaration = fitnessVertexDeclaration;                            fitnessEffect.Technique = "VersionOneOtherParts";                            fitnessEffect.SetValue("TextureOne", fitnessTexture1);                            fitnessEffect.SetValue("FitnessMatrix", fitnessMatrix);                            fitnessEffect.SetValue("xOffset", (float)(0.5 / (double)logWidth));                            fitnessEffect.SetValue("yOffset", (float)(0.5 / (double)logHeight));                            fitnessEffect.Begin(0);                            fitnessEffect.BeginPass(0);                            device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);                            fitnessEffect.EndPass();                            fitnessEffect.End();                            fitnessRenderToSurface2.EndScene(Filter.None);                            activeLogHeight /= 2;                            activeLogWidth /= 2;                        }                        if (activeLogHeight > 1 && activeLogWidth > 1 && activeLogWidth * activeLogHeight > 512)                        {                            fitnessRenderToSurface1.BeginScene(fitnessSurface1);                            device.VertexFormat = CustomVertex.PositionTextured.Format;                            device.SetStreamSource(0, fitnessVBSixteenth, 0);                            device.VertexDeclaration = fitnessVertexDeclaration;                            fitnessEffect.Technique = "VersionOneOtherParts";                            fitnessEffect.SetValue("TextureOne", fitnessTexture2);                            fitnessEffect.SetValue("FitnessMatrix", fitnessMatrix);                            fitnessEffect.SetValue("xOffset", (float)(0.5 / (double)logWidth));                            fitnessEffect.SetValue("yOffset", (float)(0.5 / (double)logHeight));                            fitnessEffect.Begin(0);                            fitnessEffect.BeginPass(0);                            device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);                            fitnessEffect.EndPass();                            fitnessEffect.End();                            fitnessRenderToSurface1.EndScene(Filter.None);                            activeLogHeight /= 2;                            activeLogWidth /= 2;                        }                        if (activeLogHeight > 1 && activeLogWidth > 1 && activeLogWidth * activeLogHeight > 512)                        {                            fitnessRenderToSurface2.BeginScene(fitnessSurface2);                            device.VertexFormat = CustomVertex.PositionTextured.Format;                            device.SetStreamSource(0, fitnessVBThirtySecond, 0);                            device.VertexDeclaration = fitnessVertexDeclaration;                            fitnessEffect.Technique = "VersionOneOtherParts";                            fitnessEffect.SetValue("TextureOne", fitnessTexture1);                            fitnessEffect.SetValue("FitnessMatrix", fitnessMatrix);                            fitnessEffect.SetValue("xOffset", (float)(0.5 / (double)logWidth));                            fitnessEffect.SetValue("yOffset", (float)(0.5 / (double)logHeight));                            fitnessEffect.Begin(0);                            fitnessEffect.BeginPass(0);                            device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);                            fitnessEffect.EndPass();                            fitnessEffect.End();                            fitnessRenderToSurface2.EndScene(Filter.None);                            activeLogHeight /= 2;                            activeLogWidth /= 2;                        }                        if (activeLogHeight > 1 && activeLogWidth > 1 && activeLogWidth * activeLogHeight > 512)                        {                            fitnessRenderToSurface1.BeginScene(fitnessSurface1);                            device.VertexFormat = CustomVertex.PositionTextured.Format;                            device.SetStreamSource(0, fitnessVBSixtyFourth, 0);                            device.VertexDeclaration = fitnessVertexDeclaration;                            fitnessEffect.Technique = "VersionOneOtherParts";                            fitnessEffect.SetValue("TextureOne", fitnessTexture2);                            fitnessEffect.SetValue("FitnessMatrix", fitnessMatrix);                            fitnessEffect.SetValue("xOffset", (float)(0.5 / (double)logWidth));                            fitnessEffect.SetValue("yOffset", (float)(0.5 / (double)logHeight));                            fitnessEffect.Begin(0);                            fitnessEffect.BeginPass(0);                            device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);                            fitnessEffect.EndPass();                            fitnessEffect.End();                            fitnessRenderToSurface1.EndScene(Filter.None);                            activeLogHeight /= 2;                            activeLogWidth /= 2;                        }                        if (activeLogHeight > 1 && activeLogWidth > 1 && activeLogWidth * activeLogHeight > 512)                        {                            fitnessRenderToSurface2.BeginScene(fitnessSurface2);                            device.VertexFormat = CustomVertex.PositionTextured.Format;                            device.SetStreamSource(0, fitnessVB128, 0);                            device.VertexDeclaration = fitnessVertexDeclaration;                            fitnessEffect.Technique = "VersionOneOtherParts";                            fitnessEffect.SetValue("TextureOne", fitnessTexture1);                            fitnessEffect.SetValue("FitnessMatrix", fitnessMatrix);                            fitnessEffect.SetValue("xOffset", (float)(0.5 / (double)logWidth));                            fitnessEffect.SetValue("yOffset", (float)(0.5 / (double)logHeight));                            fitnessEffect.Begin(0);                            fitnessEffect.BeginPass(0);                            device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);                            fitnessEffect.EndPass();                            fitnessEffect.End();                            fitnessRenderToSurface2.EndScene(Filter.None);                            activeLogHeight /= 2;                            activeLogWidth /= 2;                        }                        if (activeLogHeight > 1 && activeLogWidth > 1 && activeLogWidth * activeLogHeight > 512)                        {                            fitnessRenderToSurface1.BeginScene(fitnessSurface1);                            device.Clear(ClearFlags.Target, Color.Black, 1.0f, 0);                            device.VertexFormat = CustomVertex.PositionTextured.Format;                            device.SetStreamSource(0, fitnessVB256, 0);                            device.VertexDeclaration = fitnessVertexDeclaration;                            fitnessEffect.Technique = "VersionOneOtherParts";                            fitnessEffect.SetValue("TextureOne", fitnessTexture2);                            fitnessEffect.SetValue("FitnessMatrix", fitnessMatrix);                            fitnessEffect.SetValue("xOffset", (float)(0.5 / (double)logWidth));                            fitnessEffect.SetValue("yOffset", (float)(0.5 / (double)logHeight));                            fitnessEffect.Begin(0);                            fitnessEffect.BeginPass(0);                            device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);                            fitnessEffect.EndPass();                            fitnessEffect.End();                            fitnessRenderToSurface1.EndScene(Filter.None);                            activeLogHeight /= 2;                            activeLogWidth /= 2;                        }                        if (activeLogHeight > 1 && activeLogWidth > 1 && activeLogWidth * activeLogHeight > 512)                        {                            fitnessRenderToSurface2.BeginScene(fitnessSurface2);                            device.Clear(ClearFlags.Target, Color.Black, 1.0f, 0);                            device.VertexFormat = CustomVertex.PositionTextured.Format;                            device.SetStreamSource(0, fitnessVB512, 0);                            device.VertexDeclaration = fitnessVertexDeclaration;                            fitnessEffect.Technique = "VersionOneOtherParts";                            fitnessEffect.SetValue("TextureOne", fitnessTexture1);                            fitnessEffect.SetValue("FitnessMatrix", fitnessMatrix);                            fitnessEffect.SetValue("xOffset", (float)(0.5 / (double)logWidth));                            fitnessEffect.SetValue("yOffset", (float)(0.5 / (double)logHeight));                            fitnessEffect.Begin(0);                            fitnessEffect.BeginPass(0);                            device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);                            fitnessEffect.EndPass();                            fitnessEffect.End();                            fitnessRenderToSurface2.EndScene(Filter.None);                            activeLogHeight /= 2;                            activeLogWidth /= 2;                        }                        if (activeLogHeight > 1 && activeLogWidth > 1 && activeLogWidth * activeLogHeight > 512)                        {                            fitnessRenderToSurface1.BeginScene(fitnessSurface1);                            device.Clear(ClearFlags.Target, Color.Black, 1.0f, 0);                            device.VertexFormat = CustomVertex.PositionTextured.Format;                            device.SetStreamSource(0, fitnessVB1024, 0);                            device.VertexDeclaration = fitnessVertexDeclaration;                            fitnessEffect.Technique = "VersionOneOtherParts";                            fitnessEffect.SetValue("TextureOne", fitnessTexture2);                            fitnessEffect.SetValue("FitnessMatrix", fitnessMatrix);                            fitnessEffect.SetValue("xOffset", (float)(0.5 / (double)logWidth));                            fitnessEffect.SetValue("yOffset", (float)(0.5 / (double)logHeight));                            fitnessEffect.Begin(0);                            fitnessEffect.BeginPass(0);                            device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);                            fitnessEffect.EndPass();                            fitnessEffect.End();                            fitnessRenderToSurface1.EndScene(Filter.None);                            activeLogHeight /= 2;                            activeLogWidth /= 2;                        }                        #endregion


Running the code in PIX in single-frame (F12) mode and expanding the BeginPass(0) and EndPass() calls in the viewer will give you insight into the unnecessary state changes that are taking place. Note especially (in the CPU-time graph) that these state changes take up the bulk of the code running time.

[Edited by - StarBP on June 22, 2009 10:40:58 AM]

This topic is closed to new replies.

Advertisement