Ejemplo n.º 1
0
        public unsafe void SetShaderConstantBuffers()
        {
            ConstantBuffer <Vector4> cb0 = BufferFactory.NewConstantBuffer <Vector4>().WithUsage(ResourceUsage.DiscardWrite);
            ConstantBuffer <Matrix>  cb1 = BufferFactory.NewConstantBuffer <Matrix>().WithUsage(ResourceUsage.DiscardWrite);

            Shader shader = new FragmentShader(
                @"Tests\SimpleFS.cso",
                new ConstantBufferBinding(0U, "CB0", cb0),
                new ConstantBufferBinding(1U, "CB1", cb1)
                );

            RenderCommand testCommand = RenderCommand.SetShaderConstantBuffers(shader);

            Assert.AreEqual(RenderCommandInstruction.FSSetCBuffers, testCommand.Instruction);
            ResourceHandle *resHandleArray = (ResourceHandle *)new IntPtr(UnsafeUtils.Reinterpret <RenderCommandArgument, long>(testCommand.Arg1, sizeof(long)));

            Assert.AreEqual(cb0.ResourceHandle, resHandleArray[0]);
            Assert.AreEqual(cb1.ResourceHandle, resHandleArray[1]);
            Assert.AreEqual((RenderCommandArgument)shader.NumConstantBufferSlots, testCommand.Arg2);

            shader.Dispose();
            cb1.Dispose();
            cb0.Dispose();

#if !DEVELOPMENT && !RELEASE
            try {
                RenderCommand.SetShaderConstantBuffers(null);
                Assert.Fail();
            }
            catch (AssuranceFailedException) { }

            try {
                RenderCommand.SetShaderConstantBuffers(shader);
                Assert.Fail();
            }
            catch (AssuranceFailedException) { }
#endif
        }
Ejemplo n.º 2
0
        public void TestSettingMaterialProperties()
        {
            ConstantBuffer <Vector4> matColorBuffer = BufferFactory.NewConstantBuffer <Vector4>().WithUsage(ResourceUsage.DiscardWrite);
            TextureSampler           textureSampler = new TextureSampler(TextureFilterType.Anisotropic, TextureWrapMode.Border, AnisotropicFilteringLevel.EightTimes);
            FragmentShader           testFS         = new FragmentShader(
                @"Tests\SimpleFS.cso",
                new ConstantBufferBinding(0U, "MaterialColor", matColorBuffer),
                new TextureSamplerBinding(0U, "DefaultSampler")
                );

            Material testMaterial = new Material("Test Material", testFS);

            testMaterial.SetMaterialConstantValue((ConstantBufferBinding)testFS.GetBindingByIdentifier("MaterialColor"), Vector4.ONE);
            testMaterial.SetMaterialResource((TextureSamplerBinding)testFS.GetBindingByIdentifier("DefaultSampler"), textureSampler);

#if !DEVELOPMENT && !RELEASE
            ConstantBufferBinding cb = new ConstantBufferBinding(1U, "Test", matColorBuffer);
            try {
                testMaterial.SetMaterialConstantValue(cb, Vector4.RIGHT);
                Assert.Fail();
            }
            catch (AssuranceFailedException) { }
            finally {
                (cb as IDisposable).Dispose();
            }

            try {
                testMaterial.SetMaterialConstantValue((ConstantBufferBinding)testFS.GetBindingByIdentifier("MaterialColor"), Matrix.IDENTITY);
                Assert.Fail();
            }
            catch (AssuranceFailedException) { }
#endif

            testFS.Dispose();
            matColorBuffer.Dispose();
            testMaterial.Dispose();
            textureSampler.Dispose();
        }
Ejemplo n.º 3
0
        public void TestSetShader()
        {
            ConstantBuffer <Matrix> vpMat = BufferFactory.NewConstantBuffer <Matrix>().WithUsage(ResourceUsage.DiscardWrite);
            VertexShader            vs    = VertexShader.NewDefaultShader(vpMat);

            ConstantBuffer <Vector4> colorVec = BufferFactory.NewConstantBuffer <Vector4>().WithUsage(ResourceUsage.DiscardWrite);
            FragmentShader           fs       = new FragmentShader(@"Tests\SimpleFS.cso", new ConstantBufferBinding(0U, "MaterialProperties", colorVec));

            RenderCommand testCommand = RenderCommand.SetShader(vs);

            Assert.AreEqual(RenderCommandInstruction.VSSetShader, testCommand.Instruction);
            Assert.AreEqual((RenderCommandArgument)(IntPtr)vs.Handle, testCommand.Arg1);

            testCommand = RenderCommand.SetShader(fs);
            Assert.AreEqual(RenderCommandInstruction.FSSetShader, testCommand.Instruction);
            Assert.AreEqual((RenderCommandArgument)(IntPtr)fs.Handle, testCommand.Arg1);

#if !DEVELOPMENT && !RELEASE
            try {
                RenderCommand.SetShader(null);
                Assert.Fail();
            }
            catch (AssuranceFailedException) { }
#endif

            vs.Dispose();
            fs.Dispose();
            vpMat.Dispose();
            colorVec.Dispose();

#if !DEVELOPMENT && !RELEASE
            try {
                RenderCommand.SetShader(fs);
                Assert.Fail();
            }
            catch (AssuranceFailedException) { }
#endif
        }
Ejemplo n.º 4
0
        public static Font Load(string fontFile, FragmentShader textFS, uint?lineHeightPixels, int?kerningPixels)
        {
            Assure.NotNull(fontFile);
            Assure.NotNull(textFS);
            Assure.False(textFS.IsDisposed);
            if (!IOUtils.IsValidFilePath(fontFile) || !File.Exists(fontFile))
            {
                throw new FileNotFoundException("File '" + fontFile + "' not found: Could not load font.");
            }

            XDocument fontDocument  = XDocument.Load(fontFile, LoadOptions.None);
            XElement  root          = fontDocument.Root;
            XElement  commonElement = root.Element("common");

            if (commonElement == null)
            {
                throw new InvalidOperationException("Could not find common element in given font file.");
            }

            string name = Path.GetFileNameWithoutExtension(fontFile).CapitalizeFirst();
            uint   texWidth;
            uint   texHeight;

            try {
                texWidth  = uint.Parse(commonElement.Attribute("scaleW").Value);
                texHeight = uint.Parse(commonElement.Attribute("scaleH").Value);
                if (lineHeightPixels == null)
                {
                    lineHeightPixels = uint.Parse(commonElement.Attribute("lineHeight").Value) / 2U;
                }
            }
            catch (Exception e) {
                throw new InvalidOperationException("Could not read scaleW, scaleH, or lineHeight value!", e);
            }

            XElement pagesElement = root.Element("pages");
            IEnumerable <XElement> pageElements = pagesElement.Elements("page");

            ITexture2D[]         pageArray          = new ITexture2D[pageElements.Count()];
            ShaderResourceView[] characterPageViews = new ShaderResourceView[pageArray.Length];

            foreach (XElement pageElement in pageElements)
            {
                int    id;
                string filename;
                try {
                    id       = int.Parse(pageElement.Attribute("id").Value);
                    filename = pageElement.Attribute("file").Value;
                }
                catch (Exception e) {
                    throw new InvalidOperationException("Could not read page ID or filename for page " + pageElement + ".", e);
                }

                string fullFilename = Path.Combine(Path.GetDirectoryName(fontFile), filename);
                if (!IOUtils.IsValidFilePath(fullFilename) || !File.Exists(fullFilename))
                {
                    throw new InvalidOperationException("Page file '" + fullFilename + "' does not exist!");
                }
                if (id < 0 || id >= pageArray.Length || pageArray[id] != null)
                {
                    throw new InvalidOperationException("Invalid or duplicate page ID '" + id + "'.");
                }

                pageArray[id] = TextureFactory.LoadTexture2D()
                                .WithFilePath(fullFilename)
                                .WithPermittedBindings(GPUBindings.ReadableShaderResource)
                                .WithUsage(ResourceUsage.Immutable)
                                .Create();

                characterPageViews[id] = pageArray[id].CreateView();
            }

            GeometryCacheBuilder <DefaultVertex> characterCacheBuilder = new GeometryCacheBuilder <DefaultVertex>();
            Dictionary <char, FontCharacter>     charMap = new Dictionary <char, FontCharacter>();
            XElement charsElement = root.Element("chars");

            foreach (XElement charElement in charsElement.Elements("char"))
            {
                char unicodeValue;
                uint x, y, width, height;
                int  pageID, yOffset;

                try {
                    unicodeValue = (char)short.Parse(charElement.Attribute("id").Value);
                    x            = uint.Parse(charElement.Attribute("x").Value);
                    y            = uint.Parse(charElement.Attribute("y").Value);
                    width        = uint.Parse(charElement.Attribute("width").Value);
                    height       = uint.Parse(charElement.Attribute("height").Value);
                    pageID       = int.Parse(charElement.Attribute("page").Value);
                    yOffset      = int.Parse(charElement.Attribute("yoffset").Value);
                }
                catch (Exception e) {
                    throw new InvalidOperationException("Could not acquire character ID, page ID, or dimensions for char " + charElement + ".", e);
                }

                Rectangle charMapBoundary = new Rectangle(x, y, width, height);

                ModelHandle modelHandle = characterCacheBuilder.AddModel(
                    "Font_" + name + "_Character_" + unicodeValue,
                    new[] {
                    new DefaultVertex(
                        new Vector3(0f, 0f, 1f),
                        Vector3.BACKWARD, new Vector2(
                            charMapBoundary.GetCornerX(Rectangle.RectangleCorner.BottomLeft) / texWidth,
                            charMapBoundary.GetCornerY(Rectangle.RectangleCorner.BottomLeft) / texHeight
                            )),
                    new DefaultVertex(
                        new Vector3(charMapBoundary.Width, 0f, 1f),
                        Vector3.BACKWARD, new Vector2(
                            charMapBoundary.GetCornerX(Rectangle.RectangleCorner.BottomRight) / texWidth,
                            charMapBoundary.GetCornerY(Rectangle.RectangleCorner.BottomRight) / texHeight
                            )),
                    new DefaultVertex(
                        new Vector3(charMapBoundary.Width, -charMapBoundary.Height, 1f),
                        Vector3.BACKWARD, new Vector2(
                            charMapBoundary.GetCornerX(Rectangle.RectangleCorner.TopRight) / texWidth,
                            charMapBoundary.GetCornerY(Rectangle.RectangleCorner.TopRight) / texHeight
                            )),
                    new DefaultVertex(
                        new Vector3(0f, -charMapBoundary.Height, 1f),
                        Vector3.BACKWARD, new Vector2(
                            charMapBoundary.GetCornerX(Rectangle.RectangleCorner.TopLeft) / texWidth,
                            charMapBoundary.GetCornerY(Rectangle.RectangleCorner.TopLeft) / texHeight
                            )),
                },
                    new[] { 0U, 1U, 3U, 1U, 2U, 3U }
                    );

                //yOffset = 0;
                //if (unicodeValue == '.') yOffset = (int) (lineHeightPixels.Value * 0.9f);

                charMap.Add(
                    unicodeValue,
                    new FontCharacter(
                        unicodeValue,
                        charMapBoundary,
                        modelHandle,
                        textFS,
                        characterPageViews[pageID],
                        yOffset
                        )
                    );
            }

            if (kerningPixels == null)
            {
                kerningPixels = (int)(charMap.Values.Max(value => value.Boundary.Width) * 0.15f);
            }

            uint maxCharHeight = (uint)charMap.Values.Max(fc => fc.Boundary.Height);

            return(new Font(
                       name,
                       lineHeightPixels.Value,
                       kerningPixels.Value,
                       characterCacheBuilder.Build(),
                       pageArray,
                       characterPageViews,
                       charMap,
                       (ConstantBufferBinding)textFS.GetBindingByIdentifier(TEXT_COLOR_SHADER_CB_NAME),
                       maxCharHeight
                       ));
        }
Ejemplo n.º 5
0
        public void TestAllowsDuplicateSlotsForDifferentBindingTypes()
        {
            Shader shader = new FragmentShader(@"Tests\SimpleFS.cso", new TextureSamplerBinding(0U, "A"), new ResourceViewBinding(0U, "B"));

            shader.Dispose();
        }
Ejemplo n.º 6
0
 public void TestDisallowsDuplicateBindingSlots()
 {
     Shader shader = new FragmentShader(@"Tests\SimpleFS.cso", new TextureSamplerBinding(0U, "A"), new TextureSamplerBinding(0U, "B"));
 }
Ejemplo n.º 7
0
 public void TestDisallowsDuplicateBindingNames()
 {
     Shader shader = new FragmentShader(@"Tests\SimpleFS.cso", new ResourceViewBinding(0U, "A"), new ResourceViewBinding(1U, "A"));
 }
        private void RenderCache_IterateMaterial(int materialIndex)
        {
            // Set up context variables
            KeyValuePair <Material, ModelInstanceManager.MIDArray> currentKVP = currentInstanceData[materialIndex];
            Material currentMaterial = currentKVP.Key;

            ModelInstanceManager.MIDArray currentMID = currentKVP.Value;

            // Skip this material if it or its shader are disposed
            if (currentMaterial.IsDisposed || currentMaterial.Shader.IsDisposed)
            {
                return;
            }

            // Skip this material if we're not using it
            bool inUse = false;

            for (int i = 0; i < currentMID.Length; ++i)
            {
                if (currentMID.Data[i].InUse)
                {
                    inUse = true;
                    break;
                }
            }
            if (!inUse)
            {
                return;
            }

            // Prepare shader according to material params, and switch to it or update it
            if (lastSetFragmentShader != currentMaterial.Shader || lastFrameNum != frameNum)
            {
                lastSetFragmentShader = currentMaterial.Shader;
                lastFrameNum          = frameNum;
                QueueShaderSwitch(lastSetFragmentShader);
            }
            var queuedSRP = currentMaterial.FragmentShaderResourcePackage;

            if (lastSetFragmentShader == geomFSWithShadowSupport)
            {
                if (modifiedSRP == null)
                {
                    modifiedSRP = new ShaderResourcePackage();
                }
                modifiedSRP.CopyFrom(queuedSRP);
                modifiedSRP.SetValue((ResourceViewBinding)lastSetFragmentShader.GetBindingByIdentifier("ShadowMap"), previousShadowBufferSRV);
                queuedSRP = modifiedSRP;
            }
            QueueShaderResourceUpdate(lastSetFragmentShader, queuedSRP);

            // Filter & sort
            if (materialFilteringWorkspace == null || materialFilteringWorkspace.Length < currentCache.NumModels)
            {
                materialFilteringWorkspace = new FastClearList <Transform> [currentCache.NumModels];
                for (int i = 0; i < materialFilteringWorkspace.Length; ++i)
                {
                    materialFilteringWorkspace[i] = new FastClearList <Transform>();
                }
            }
            for (int i = 0; i < materialFilteringWorkspace.Length; ++i)
            {
                materialFilteringWorkspace[i].Clear();
            }

            SortByProximityToCamera(currentMID);
            uint numInstances = 0U;

            for (uint i = 0U; i < currentMID.Length; ++i)
            {
                ModelInstanceData curMID = sortedModelData[i];
                if (!curMID.InUse)
                {
                    continue;
                }
                SceneLayer layer = currentSceneLayers[curMID.SceneLayerIndex];
                if (layer == null || !layer.GetRenderingEnabled() || !addedSceneLayers.Contains(layer))
                {
                    continue;
                }

                if (curMID.ModelIndex == __VEGG_MH.ModelIndex && currentCache.ID == __VEGG_MH.GeoCacheID)
                {
                    int instanceIndex = 0;
                    for (int j = 0; j < currentMID.Length; ++j)
                    {
                        if (currentMID.Data[j].Transform == curMID.Transform)
                        {
                            instanceIndex = j;
                            break;
                        }
                    }
                    Quaternion rot = Quaternion.IDENTITY;
                    foreach (var kvp in __VEGG_MIH_ARR)
                    {
                        if (kvp.Key.InstanceIndex == instanceIndex)
                        {
                            rot = kvp.Value;
                            break;
                        }
                    }
                    materialFilteringWorkspace[curMID.ModelIndex].Add(curMID.Transform.RotateBy(rot));
                }
                else
                {
                    materialFilteringWorkspace[curMID.ModelIndex].Add(curMID.Transform);
                }
                ++numInstances;
            }

            // Concatenate & queue render commands
            if (instanceConcatWorkspace == null || instanceConcatWorkspace.Length < numInstances)
            {
                instanceConcatWorkspace = new Matrix[numInstances << 1];                 // x2 so we don't create loads of garbage if the count keeps increasing by 1
            }

            uint instanceStartOffset = RenderCache_IterateMaterial_ConcatReserve(numInstances);
            uint nextWorkspaceIndex = 0;
            uint outVBStartIndex, outIBStartIndex, outVBCount, outIBCount;

            for (uint mI = 0U; mI < materialFilteringWorkspace.Length; ++mI)
            {
                FastClearList <Transform> filteredTransformList = materialFilteringWorkspace[mI];
                int numFilteredTransforms = filteredTransformList.Count;
                if (numFilteredTransforms == 0)
                {
                    continue;
                }

                currentCache.GetModelBufferValues(mI, out outVBStartIndex, out outIBStartIndex, out outVBCount, out outIBCount);

                QueueRenderCommand(RenderCommand.DrawIndexedInstanced(
                                       (int)outVBStartIndex,
                                       outIBStartIndex,
                                       outIBCount,
                                       nextWorkspaceIndex + instanceStartOffset,
                                       (uint)numFilteredTransforms
                                       ));

                for (int iI = 0; iI < numFilteredTransforms; ++iI)
                {
                    if (mI == __EGGHACK_MH.ModelIndex && currentCache.ID == __EGGHACK_MH.GeoCacheID)
                    {
                        instanceConcatWorkspace[nextWorkspaceIndex++] = filteredTransformList[iI].RotateBy(__EGGHACK_ROT).AsMatrixTransposed;
                    }
                    else
                    {
                        instanceConcatWorkspace[nextWorkspaceIndex++] = filteredTransformList[iI].AsMatrixTransposed;
                    }
                }
            }

            RenderCache_IterateMaterial_Concat(instanceConcatWorkspace, instanceStartOffset, numInstances);
        }
Ejemplo n.º 9
0
 public FontCharacter(char unicodeValue, Rectangle boundary, ModelHandle modelHandle, FragmentShader fragmentShader, ShaderResourceView fontMapResourceView, int yOffset)
 {
     UnicodeValue        = unicodeValue;
     Boundary            = boundary;
     ModelHandle         = modelHandle;
     FragmentShader      = fragmentShader;
     FontMapResourceView = fontMapResourceView;
     YOffset             = yOffset;
 }
Ejemplo n.º 10
0
        private void RenderCache_IterateMaterial(int materialIndex)
        {
            // Set up context variables
            KeyValuePair <Material, ModelInstanceManager.MIDArray> currentKVP = currentInstanceData[materialIndex];
            Material currentMaterial = currentKVP.Key;

            ModelInstanceManager.MIDArray currentMID = currentKVP.Value;

            // Skip this material if it or its shader are disposed
            if (currentMaterial.IsDisposed || currentMaterial.Shader.IsDisposed)
            {
                return;
            }

            // Prepare shader according to material params, and switch to it or update it
            if (lastSetFragmentShader != currentMaterial.Shader || lastFrameNum != frameNum)
            {
                lastSetFragmentShader = currentMaterial.Shader;
                lastFrameNum          = frameNum;
                QueueShaderSwitch(lastSetFragmentShader);
            }
            QueueShaderResourceUpdate(lastSetFragmentShader, currentMaterial.FragmentShaderResourcePackage);


            // Filter & sort
            if (materialFilteringWorkspace == null || materialFilteringWorkspace.Length < currentCache.NumModels)
            {
                materialFilteringWorkspace = new FastClearList <Transform> [currentCache.NumModels];
                for (int i = 0; i < materialFilteringWorkspace.Length; ++i)
                {
                    materialFilteringWorkspace[i] = new FastClearList <Transform>();
                }
            }
            for (int i = 0; i < materialFilteringWorkspace.Length; ++i)
            {
                materialFilteringWorkspace[i].Clear();
            }

            ModelInstanceData *midData = currentMID.Data;
            uint numInstances          = 0U;

            for (uint i = 0U; i < currentMID.Length; ++i)
            {
                ModelInstanceData curMID = midData[i];
                if (!curMID.InUse)
                {
                    continue;
                }
                SceneLayer layer = currentSceneLayers[curMID.SceneLayerIndex];
                if (layer == null || !layer.GetRenderingEnabled() || !addedSceneLayers.Contains(layer))
                {
                    continue;
                }

                materialFilteringWorkspace[curMID.ModelIndex].Add(curMID.Transform);
                ++numInstances;
            }

            // Concatenate & queue render commands
            if (instanceConcatWorkspace == null || instanceConcatWorkspace.Length < numInstances)
            {
                instanceConcatWorkspace = new Matrix[numInstances << 1];                 // x2 so we don't create loads of garbage if the count keeps increasing by 1
            }

            uint instanceStartOffset = RenderCache_IterateMaterial_ConcatReserve(numInstances);
            uint nextWorkspaceIndex = 0;
            uint outVBStartIndex, outIBStartIndex, outVBCount, outIBCount;

            for (uint mI = 0U; mI < materialFilteringWorkspace.Length; ++mI)
            {
                FastClearList <Transform> filteredTransformList = materialFilteringWorkspace[mI];
                int numFilteredTransforms = filteredTransformList.Count;
                if (numFilteredTransforms == 0)
                {
                    continue;
                }

                currentCache.GetModelBufferValues(mI, out outVBStartIndex, out outIBStartIndex, out outVBCount, out outIBCount);

                QueueRenderCommand(RenderCommand.DrawIndexedInstanced(
                                       (int)outVBStartIndex,
                                       outIBStartIndex,
                                       outIBCount,
                                       nextWorkspaceIndex + instanceStartOffset,
                                       (uint)numFilteredTransforms
                                       ));

                for (int iI = 0; iI < numFilteredTransforms; ++iI)
                {
                    instanceConcatWorkspace[nextWorkspaceIndex++] = filteredTransformList[iI].AsMatrixTransposed;
                }
            }

            RenderCache_IterateMaterial_Concat(instanceConcatWorkspace, instanceStartOffset, numInstances);
        }
Ejemplo n.º 11
0
        public unsafe void TestSetShaderResourceViews()
        {
            Texture2DBuilder <TexelFormat.RGBA32UInt> texBuilder = TextureFactory.NewTexture2D <TexelFormat.RGBA32UInt>()
                                                                   .WithWidth(100U)
                                                                   .WithHeight(100U)
                                                                   .WithUsage(ResourceUsage.DiscardWrite);
            Texture2D <TexelFormat.RGBA32UInt> tex0 = texBuilder.Create();
            Texture2D <TexelFormat.RGBA32UInt> tex2 = texBuilder.Create();

            BaseResourceView rv0 = tex0.CreateView();
            BaseResourceView rv2 = tex2.CreateView();

            Shader shader = new FragmentShader(
                @"Tests\SimpleFS.cso",
                new ResourceViewBinding(0U, "RV0"),
                new ResourceViewBinding(1U, "RV1"),
                new ResourceViewBinding(2U, "RV2")
                );

            Dictionary <ResourceViewBinding, BaseResourceView> rvDict = new Dictionary <ResourceViewBinding, BaseResourceView>();

            rvDict[shader.ResourceViewBindings[0]] = rv0;
            rvDict[shader.ResourceViewBindings[2]] = rv2;

            RenderCommand testCommand = RenderCommand.SetShaderResourceViews(shader, rvDict);

            Assert.AreEqual(RenderCommandInstruction.FSSetResources, testCommand.Instruction);
            ResourceViewHandle *resHandleArray = (ResourceViewHandle *)new IntPtr(UnsafeUtils.Reinterpret <RenderCommandArgument, long>(testCommand.Arg1, sizeof(long)));

            Assert.AreEqual(rv0.ResourceViewHandle, resHandleArray[0]);
            Assert.AreEqual(ResourceViewHandle.NULL, resHandleArray[1]);
            Assert.AreEqual(rv2.ResourceViewHandle, resHandleArray[2]);
            Assert.AreEqual((RenderCommandArgument)3U, testCommand.Arg2);

#if !DEVELOPMENT && !RELEASE
            try {
                RenderCommand.SetShaderResourceViews(null, rvDict);
                Assert.Fail();
            }
            catch (AssuranceFailedException) { }

            try {
                RenderCommand.SetShaderResourceViews(shader, null);
                Assert.Fail();
            }
            catch (AssuranceFailedException) { }
#endif

            tex0.Dispose();
            tex2.Dispose();
            rv0.Dispose();
            rv2.Dispose();

#if !DEVELOPMENT && !RELEASE
            try {
                RenderCommand.SetShaderResourceViews(shader, rvDict);
                Assert.Fail();
            }
            catch (AssuranceFailedException) { }
#endif

            shader.Dispose();

#if !DEVELOPMENT && !RELEASE
            try {
                RenderCommand.SetShaderResourceViews(shader, new Dictionary <ResourceViewBinding, BaseResourceView>());
                Assert.Fail();
            }
            catch (AssuranceFailedException) { }
#endif
        }
Ejemplo n.º 12
0
        public unsafe void TestSetShaderTextureSamplers()
        {
            TextureSampler ts0 = new TextureSampler(TextureFilterType.Anisotropic, TextureWrapMode.Border, AnisotropicFilteringLevel.EightTimes);
            TextureSampler ts2 = new TextureSampler(TextureFilterType.Anisotropic, TextureWrapMode.Border, AnisotropicFilteringLevel.EightTimes);

            Shader shader = new FragmentShader(
                @"Tests\SimpleFS.cso",
                new TextureSamplerBinding(0U, "TS0"),
                new TextureSamplerBinding(1U, "TS1"),
                new TextureSamplerBinding(2U, "TS2")
                );

            Dictionary <TextureSamplerBinding, TextureSampler> tsDict = new Dictionary <TextureSamplerBinding, TextureSampler>();

            tsDict[shader.TextureSamplerBindings[0]] = ts0;
            tsDict[shader.TextureSamplerBindings[2]] = ts2;

            RenderCommand testCommand = RenderCommand.SetShaderTextureSamplers(shader, tsDict);

            Assert.AreEqual(RenderCommandInstruction.FSSetSamplers, testCommand.Instruction);
            ResourceHandle *resHandleArray = (ResourceHandle *)new IntPtr(UnsafeUtils.Reinterpret <RenderCommandArgument, long>(testCommand.Arg1, sizeof(long)));

            Assert.AreEqual(ts0.ResourceHandle, resHandleArray[0]);
            Assert.AreEqual(ResourceHandle.NULL, resHandleArray[1]);
            Assert.AreEqual(ts2.ResourceHandle, resHandleArray[2]);
            Assert.AreEqual((RenderCommandArgument)3U, testCommand.Arg2);

#if !DEVELOPMENT && !RELEASE
            try {
                RenderCommand.SetShaderTextureSamplers(null, tsDict);
                Assert.Fail();
            }
            catch (AssuranceFailedException) { }

            try {
                RenderCommand.SetShaderTextureSamplers(shader, null);
                Assert.Fail();
            }
            catch (AssuranceFailedException) { }
#endif

            ts0.Dispose();
            ts2.Dispose();

#if !DEVELOPMENT && !RELEASE
            try {
                RenderCommand.SetShaderTextureSamplers(shader, tsDict);
                Assert.Fail();
            }
            catch (AssuranceFailedException) { }
#endif

            shader.Dispose();

#if !DEVELOPMENT && !RELEASE
            try {
                RenderCommand.SetShaderTextureSamplers(shader, new Dictionary <TextureSamplerBinding, TextureSampler>());
                Assert.Fail();
            }
            catch (AssuranceFailedException) { }
#endif
        }
        public unsafe void TestCreateAndDestroyInstance()
        {
            // Define variables and constants
            const int NUM_INSTANCES = 1000;

            var gcb = new GeometryCacheBuilder <TestVertex>();

            gcb.AddModel("TCADI_a", new[] { new TestVertex(Vector3.ONE), new TestVertex(Vector3.LEFT), }, new[] { 0U, 1U, 1U, 0U, 1U, 0U });
            gcb.AddModel("TCADI_b", new[] { new TestVertex(Vector3.RIGHT), new TestVertex(Vector3.UP), }, new[] { 0U, 1U, 1U, 0U, 1U, 0U });
            gcb.AddModel("TCADI_c", new[] { new TestVertex(Vector3.ZERO), new TestVertex(Vector3.DOWN), }, new[] { 0U, 1U, 1U, 0U, 1U, 0U });
            GeometryCache testCache = gcb.Build();

            SceneLayer testLayerA = Scene.CreateLayer("Test Layer A");
            SceneLayer testLayerB = Scene.CreateLayer("Test Layer B");
            ConstantBuffer <Vector4> fsColorBuffer = BufferFactory.NewConstantBuffer <Vector4>().WithUsage(ResourceUsage.DiscardWrite);
            FragmentShader           fs            = new FragmentShader(@"Tests\SimpleFS.cso", new ConstantBufferBinding(0U, "MaterialProperties", fsColorBuffer));
            Material testMatA = new Material("Brick", fs);
            Material testMatB = new Material("Wood", fs);

            // Set up context


            // Execute
            ModelInstanceHandle[] instanceArr = new ModelInstanceHandle[NUM_INSTANCES];
            for (int i = 0; i < NUM_INSTANCES; ++i)
            {
                Transform transform = new Transform(
                    Vector3.ONE * i,
                    Quaternion.FromAxialRotation(Vector3.UP, i),
                    Vector3.ONE * -i
                    );
                if (i % 5 == 0)
                {
                    instanceArr[i] = testLayerA.CreateModelInstance(new ModelHandle(testCache.ID, (uint)(i % 3)), (i % 2 == 0 ? testMatA : testMatB), transform);
                }
                else
                {
                    instanceArr[i] = testLayerB.CreateModelInstance(new ModelHandle(testCache.ID, (uint)(i % 3)), (i % 2 == 0 ? testMatA : testMatB), transform);
                }
            }

            // Assert outcome
            RenderingModule.RenderStateBarrier.FreezeMutations();             // Cheeky, but we have to on debug mode (and it's re-entrant for now, so no problem)
            var instanceData = testCache.GetModelInstanceData();

            for (int i = 0; i < NUM_INSTANCES; ++i)
            {
                Material instanceMaterial = Material.GetMaterialByIndex(instanceArr[i].MaterialIndex);
                ModelInstanceManager.MIDArray materialDataArray = instanceData.First(kvp => kvp.Key == instanceMaterial).Value;

                Assert.AreEqual((i % 2 == 0 ? testMatA : testMatB), instanceMaterial);
                Assert.AreEqual((i % 5 == 0 ? testLayerA : testLayerB), Scene.GetLayerByIndex(materialDataArray.Data[GetMIHInstanceIndex(instanceArr[i])].SceneLayerIndex));
                Assert.IsTrue(materialDataArray.Data[GetMIHInstanceIndex(instanceArr[i])].InUse);
                Assert.AreEqual((uint)(i % 3), materialDataArray.Data[GetMIHInstanceIndex(instanceArr[i])].ModelIndex);
                Assert.AreEqual(
                    new Transform(
                        Vector3.ONE * i,
                        Quaternion.FromAxialRotation(Vector3.UP, i),
                        Vector3.ONE * -i
                        ),
                    instanceArr[i].Transform
                    );
                Assert.AreEqual(instanceArr[i].Transform, materialDataArray.Data[GetMIHInstanceIndex(instanceArr[i])].Transform);

                instanceArr[i].Dispose();
                Assert.IsFalse(materialDataArray.Data[GetMIHInstanceIndex(instanceArr[i])].InUse);
            }

            RenderingModule.RenderStateBarrier.UnfreezeMutations();

            testCache.Dispose();
            testMatA.Dispose();
            testMatB.Dispose();
            testLayerA.Dispose();
            testLayerB.Dispose();
            fs.Dispose();
            fsColorBuffer.Dispose();
        }
        public void TestAllMethods()
        {
            // Define variables and constants
            ModelInstanceManager testMIM          = new ModelInstanceManager();
            const int            NUM_ALLOCATIONS  = 3000;
            const int            NUM_MODELS       = 7;
            const int            NUM_MATERIALS    = 11;
            const int            NUM_SCENE_LAYERS = 3;

            ConstantBuffer <Vector4> fsCBuffer = BufferFactory.NewConstantBuffer <Vector4>().WithUsage(ResourceUsage.DiscardWrite);
            FragmentShader           testFS    = new FragmentShader(@"Tests\SimpleFS.cso", new ConstantBufferBinding(0U, "MaterialProperties", fsCBuffer));

            Material[] materials = new Material[NUM_MATERIALS];
            for (int i = 0; i < NUM_MATERIALS; ++i)
            {
                materials[i] = new Material(i.ToString(), testFS);
            }

            // Set up context
            ModelInstanceHandle[] instances = new ModelInstanceHandle[NUM_ALLOCATIONS];

            // Execute
            for (int i = 0; i < NUM_ALLOCATIONS; i++)
            {
                Transform initialTransform = new Transform(
                    Vector3.ONE * i,
                    Quaternion.FromAxialRotation(Vector3.ONE * (i + 1), MathUtils.PI),
                    Vector3.ONE * -i
                    );
                instances[i] = testMIM.AllocateInstance(materials[i % NUM_MATERIALS].Index, (uint)i % NUM_MODELS, (uint)i % NUM_SCENE_LAYERS, initialTransform);
            }

            for (int i = 0; i < NUM_ALLOCATIONS; i += 2)
            {
                instances[i].Transform = instances[i].Transform.With(scale: Vector3.FORWARD * i);
            }

            // Assert outcome
            RenderingModule.RenderStateBarrier.FreezeMutations();
            ArraySlice <KeyValuePair <Material, ModelInstanceManager.MIDArray> > midData = testMIM.GetModelInstanceData();

            RenderingModule.RenderStateBarrier.UnfreezeMutations();
            Assert.AreEqual(NUM_ALLOCATIONS, midData.Sum(kvp => {
                unsafe {
                    int val = 0;
                    for (int i = 0; i < kvp.Value.Length; ++i)
                    {
                        if (kvp.Value.Data[i].InUse)
                        {
                            ++val;
                        }
                    }
                    return(val);
                }
            }));

            unsafe {
                foreach (KeyValuePair <Material, ModelInstanceManager.MIDArray> kvp in midData)
                {
                    Assert.IsTrue(materials.Contains(kvp.Key));
                    for (uint i = 0U; i < kvp.Value.Length; ++i)
                    {
                        if (!kvp.Value.Data[i].InUse)
                        {
                            continue;
                        }
                        Assert.AreEqual(1, instances.Count(mih => mih.Transform == kvp.Value.Data[i].Transform));
                    }
                }
            }

            materials.ForEach(mat => mat.Dispose());
            testFS.Dispose();
            fsCBuffer.Dispose();
        }