public unsafe void TestProperties()
        {
            // Define variables and constants
            const int FAKE_CACHE_ID = 1351617;

            IVertexBuffer[] buffers = new IVertexBuffer[2];
            buffers[0] = BufferFactory.NewVertexBuffer <Vector3>()
                         .WithInitialData(new[] { Vector3.ONE * 0f, Vector3.ONE * 1f, Vector3.ONE * 2f, Vector3.ONE * 3f, Vector3.ONE * 4f, Vector3.ONE * 5f })
                         .WithUsage(ResourceUsage.Immutable)
                         .Create();
            buffers[1] = BufferFactory.NewVertexBuffer <Vector2>()
                         .WithInitialData(new[] { Vector2.ONE * 0f, Vector2.ONE * 1f, Vector2.ONE * 2f, Vector2.ONE * 3f, Vector2.ONE * 4f, Vector2.ONE * 5f })
                         .WithUsage(ResourceUsage.Immutable)
                         .Create();
            string[]         semantics = { "POSITION", "TEXCOORD" };
            ResourceFormat[] formats   = { ResourceFormat.R32G32B32Float, ResourceFormat.R32G32Float };
            IndexBuffer      indices   = BufferFactory.NewIndexBuffer()
                                         .WithInitialData(new uint[] { 0, 1, 2, 1, 2, 0, 2, 1, 0, 3, 4, 5, 4, 5, 3, 5, 3, 4, 5, 3, 4 })
                                         .WithUsage(ResourceUsage.Immutable);
            AlignedAllocation <uint> componentStartPointsAlloc = AlignedAllocation <uint> .AllocArray(7L, 3);

            *(((uint *)componentStartPointsAlloc.AlignedPointer) + 0) = 0U;
            *(((uint *)componentStartPointsAlloc.AlignedPointer) + 1) = 3U;
            *(((uint *)componentStartPointsAlloc.AlignedPointer) + 2) = 6U;
            AlignedAllocation <uint> indexStartPointsAlloc = AlignedAllocation <uint> .AllocArray(7L, 3);

            *(((uint *)indexStartPointsAlloc.AlignedPointer) + 0) = 0U;
            *(((uint *)indexStartPointsAlloc.AlignedPointer) + 1) = 9U;
            *(((uint *)indexStartPointsAlloc.AlignedPointer) + 2) = 21U;
            Dictionary <string, ModelHandle> modelNameMap = new Dictionary <string, ModelHandle>()
            {
                { FAKE_CACHE_ID + "A", new ModelHandle(FAKE_CACHE_ID, 0U) },
                { FAKE_CACHE_ID + "B", new ModelHandle(FAKE_CACHE_ID, 1U) }
            };
            const uint NUM_MODELS = 2;

            // Set up context
            GeometryCache cache = new GeometryCache(
                buffers, semantics, formats,
                indices, componentStartPointsAlloc, indexStartPointsAlloc,
                NUM_MODELS, typeof(FakeVertex), FAKE_CACHE_ID, modelNameMap
                );


            // Execute


            // Assert outcome
            Assert.AreEqual(buffers[0], cache.VertexBuffers[0]);
            Assert.AreEqual(buffers[1], cache.VertexBuffers[1]);
            Assert.AreEqual(semantics[0], cache.VertexSemantics[0]);
            Assert.AreEqual(semantics[1], cache.VertexSemantics[1]);
            Assert.AreEqual(formats[0], cache.VertexFormats[0]);
            Assert.AreEqual(formats[1], cache.VertexFormats[1]);
            Assert.AreEqual(indices, cache.IndexBuffer);

            cache.Dispose();
        }
示例#2
0
 public void Dispose()
 {
     lock (instanceMutationLock) {
         if (isDisposed)
         {
             return;
         }
         CharacterGeometry.Dispose();
         characterPages.ForEach(page => page.Dispose());
         characterPageViews.ForEach(view => view.Dispose());
         isDisposed = true;
     }
 }
        public void ShouldRejectDuplicateModelNames()
        {
            GeometryCacheBuilder <DefaultVertex> gcbA = new GeometryCacheBuilder <DefaultVertex>();

            gcbA.AddModel("SRDMN_A", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U });
            gcbA.AddModel("SRDMN_B", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U });

            GeometryCache gcA = gcbA.Build();

            GeometryCacheBuilder <DefaultVertex> gcbB = new GeometryCacheBuilder <DefaultVertex>();

            gcbB.AddModel("SRDMN_1", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U });
            gcbB.AddModel("SRDMN_2", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U });
            gcbB.AddModel("SRDMN_3", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U });
            GeometryCache gcB = gcbB.Build();

            GeometryCacheBuilder <DefaultVertex> gcbC = new GeometryCacheBuilder <DefaultVertex>();

            gcbC.AddModel("SRDMN_1", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U });
            try {
                gcbC.Build();
                Assert.Fail();
            }
            catch (InvalidOperationException) { }

            gcbC = new GeometryCacheBuilder <DefaultVertex>();
            gcbC.AddModel("SRDMN_A", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U });
            try {
                gcbC.Build();
                Assert.Fail();
            }
            catch (InvalidOperationException) { }

            gcbC = new GeometryCacheBuilder <DefaultVertex>();
            gcbC.AddModel("SRDMN_X", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U });
            gcbC.AddModel("SRDMN_Y", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U });
            gcbC.AddModel("SRDMN_Z", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U });
            gcbC.AddModel("SRDMN_Z", new[] { new DefaultVertex(Vector3.ONE) }, new[] { 1U });
            try {
                gcbC.Build();
                Assert.Fail();
            }
            catch (InvalidOperationException) { }

            gcA.Dispose();
            gcB.Dispose();
        }
        public void TestSetInputLayout()
        {
            GeometryCacheBuilder <DefaultVertex> gcb = new GeometryCacheBuilder <DefaultVertex>();

            gcb.AddModel("TSIL_a", new DefaultVertex[] { new DefaultVertex(Vector3.ONE) }, new uint[] { 0U });
            GeometryCache           cache  = gcb.Build();
            ConstantBuffer <Matrix> vpMat  = BufferFactory.NewConstantBuffer <Matrix>().WithUsage(ResourceUsage.DiscardWrite);
            VertexShader            shader = new VertexShader(
                @"Tests\SimpleVS.cso",
                new VertexInputBinding(0U, "INSTANCE_TRANSFORM"),
                new ConstantBufferBinding(0U, "CameraTransform", vpMat),
                new VertexInputBinding(1U, "POSITION")
                );

            GeometryInputLayout gil = cache.GetInputLayout(shader);

            RenderCommand testCommand = RenderCommand.SetInputLayout(gil);

            Assert.AreEqual(RenderCommandInstruction.SetInputLayout, testCommand.Instruction);
            Assert.AreEqual((RenderCommandArgument)(IntPtr)gil.ResourceHandle, testCommand.Arg1);

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

            shader.Dispose();
            vpMat.Dispose();
            cache.Dispose();
            gil.Dispose();

#if !DEVELOPMENT && !RELEASE
            try {
                RenderCommand.SetInputLayout(gil);
                Assert.Fail();
            }
            catch (AssuranceFailedException) { }
#endif
        }
        public unsafe void TestGetModelBufferValues()
        {
            // Define variables and constants
            const int FAKE_CACHE_ID = 1351616;

            IVertexBuffer[] buffers = new IVertexBuffer[2];
            buffers[0] = BufferFactory.NewVertexBuffer <Vector3>()
                         .WithInitialData(new[] { Vector3.ONE * 0f, Vector3.ONE * 1f, Vector3.ONE * 2f, Vector3.ONE * 3f, Vector3.ONE * 4f, Vector3.ONE * 5f })
                         .WithUsage(ResourceUsage.Immutable)
                         .Create();
            buffers[1] = BufferFactory.NewVertexBuffer <Vector2>()
                         .WithInitialData(new[] { Vector2.ONE * 0f, Vector2.ONE * 1f, Vector2.ONE * 2f, Vector2.ONE * 3f, Vector2.ONE * 4f, Vector2.ONE * 5f })
                         .WithUsage(ResourceUsage.Immutable)
                         .Create();
            string[]         semantics = { "POSITION", "TEXCOORD" };
            ResourceFormat[] formats   = { ResourceFormat.R32G32B32Float, ResourceFormat.R32G32Float };
            IndexBuffer      indices   = BufferFactory.NewIndexBuffer()
                                         .WithInitialData(new uint[] { 0, 1, 2, 1, 2, 0, 2, 1, 0, 3, 4, 5, 4, 5, 3, 5, 3, 4, 5, 3, 4 })
                                         .WithUsage(ResourceUsage.Immutable);
            AlignedAllocation <uint> componentStartPointsAlloc = AlignedAllocation <uint> .AllocArray(7L, 3);

            *(((uint *)componentStartPointsAlloc.AlignedPointer) + 0) = 0U;
            *(((uint *)componentStartPointsAlloc.AlignedPointer) + 1) = 3U;
            *(((uint *)componentStartPointsAlloc.AlignedPointer) + 2) = 6U;
            AlignedAllocation <uint> indexStartPointsAlloc = AlignedAllocation <uint> .AllocArray(7L, 3);

            *(((uint *)indexStartPointsAlloc.AlignedPointer) + 0) = 0U;
            *(((uint *)indexStartPointsAlloc.AlignedPointer) + 1) = 9U;
            *(((uint *)indexStartPointsAlloc.AlignedPointer) + 2) = 21U;
            Dictionary <string, ModelHandle> modelNameMap = new Dictionary <string, ModelHandle>()
            {
                { FAKE_CACHE_ID + "A", new ModelHandle(FAKE_CACHE_ID, 0U) },
                { FAKE_CACHE_ID + "B", new ModelHandle(FAKE_CACHE_ID, 1U) }
            };
            const uint NUM_MODELS = 2;

            uint outVBStartIndex, outIBStartIndex, outVBCount, outIBCount;

            // Set up context
            GeometryCache cache = new GeometryCache(
                buffers, semantics, formats,
                indices, componentStartPointsAlloc, indexStartPointsAlloc,
                NUM_MODELS, typeof(FakeVertex), FAKE_CACHE_ID, modelNameMap
                );

            // Execute
            cache.GetModelBufferValues(0U, out outVBStartIndex, out outIBStartIndex, out outVBCount, out outIBCount);

            // Assert outcome
            Assert.AreEqual(0U, outVBStartIndex);
            Assert.AreEqual(0U, outIBStartIndex);
            Assert.AreEqual(3U, outVBCount);
            Assert.AreEqual(9U, outIBCount);

            cache.GetModelBufferValues(1U, out outVBStartIndex, out outIBStartIndex, out outVBCount, out outIBCount);

            Assert.AreEqual(3U, outVBStartIndex);
            Assert.AreEqual(9U, outIBStartIndex);
            Assert.AreEqual(3U, outVBCount);
            Assert.AreEqual(12U, outIBCount);

#if !DEVELOPMENT && !RELEASE
            try {
                cache.GetModelBufferValues(2U, out outVBStartIndex, out outIBStartIndex, out outVBCount, out outIBCount);
                Assert.Fail();
            }
            catch (AssuranceFailedException) { }
#endif

            cache.Dispose();
        }
        public unsafe void TestGetInputLayout()
        {
            // Define variables and constants
            const int FAKE_CACHE_ID = 1351618;

            IVertexBuffer[] buffers = new IVertexBuffer[2];
            buffers[0] = BufferFactory.NewVertexBuffer <Vector3>()
                         .WithInitialData(new[] { Vector3.ONE * 0f, Vector3.ONE * 1f, Vector3.ONE * 2f, Vector3.ONE * 3f, Vector3.ONE * 4f, Vector3.ONE * 5f })
                         .WithUsage(ResourceUsage.Immutable)
                         .Create();
            buffers[1] = BufferFactory.NewVertexBuffer <float>()
                         .WithInitialData(new[] { 0f, 1f, 2f, 3f, 4f, 5f })
                         .WithUsage(ResourceUsage.Immutable)
                         .Create();
            string[]         semantics = { "POSITION", "RANDOM_FLOATS" };
            ResourceFormat[] formats   = { ResourceFormat.R32G32B32Float, ResourceFormat.R32G32Float };
            IndexBuffer      indices   = BufferFactory.NewIndexBuffer()
                                         .WithInitialData(new uint[] { 0, 1, 2, 1, 2, 0, 2, 1, 0, 3, 4, 5, 4, 5, 3, 5, 3, 4, 5, 3, 4 })
                                         .WithUsage(ResourceUsage.Immutable);
            AlignedAllocation <uint> componentStartPointsAlloc = AlignedAllocation <uint> .AllocArray(7L, 3);

            *(((uint *)componentStartPointsAlloc.AlignedPointer) + 0) = 0U;
            *(((uint *)componentStartPointsAlloc.AlignedPointer) + 1) = 3U;
            *(((uint *)componentStartPointsAlloc.AlignedPointer) + 2) = 6U;
            AlignedAllocation <uint> indexStartPointsAlloc = AlignedAllocation <uint> .AllocArray(7L, 3);

            *(((uint *)indexStartPointsAlloc.AlignedPointer) + 0) = 0U;
            *(((uint *)indexStartPointsAlloc.AlignedPointer) + 1) = 9U;
            *(((uint *)indexStartPointsAlloc.AlignedPointer) + 2) = 21U;
            Dictionary <string, ModelHandle> modelNameMap = new Dictionary <string, ModelHandle>()
            {
                { FAKE_CACHE_ID + "A", new ModelHandle(FAKE_CACHE_ID, 0U) },
                { FAKE_CACHE_ID + "B", new ModelHandle(FAKE_CACHE_ID, 1U) }
            };
            const uint NUM_MODELS = 2;

            // Set up context
            GeometryCache cache = new GeometryCache(
                buffers, semantics, formats,
                indices, componentStartPointsAlloc, indexStartPointsAlloc,
                NUM_MODELS, typeof(Vector4), FAKE_CACHE_ID, modelNameMap
                );

            ConstantBuffer <Matrix> instanceCBuffer = BufferFactory.NewConstantBuffer <Matrix>().WithUsage(ResourceUsage.DiscardWrite);
            VertexShader            vs1             = new VertexShader(
                @"Tests\SimpleVS.cso",
                new VertexInputBinding(0U, "INSTANCE_TRANSFORM"),
                new ConstantBufferBinding(0U, "CameraTransform", instanceCBuffer),
                new VertexInputBinding(1U, "POSITION")
                );
            VertexShader vs2 = new VertexShader(
                @"Tests\SimpleVS.cso",
                new VertexInputBinding(0U, "INSTANCE_TRANSFORM"),
                new ConstantBufferBinding(0U, "CameraTransform", instanceCBuffer),
                new VertexInputBinding(1U, "RANDOM_FLOATS"),
                new VertexInputBinding(2U, "POSITION")
                );
            VertexShader vs3 = new VertexShader(
                @"Tests\SimpleVS.cso",
                new VertexInputBinding(0U, "INSTANCE"),
                new ConstantBufferBinding(0U, "VPTransform", instanceCBuffer),
                new VertexInputBinding(1U, "TEXCOORD")
                );

            // Execute
            GeometryInputLayout inputLayout1 = cache.GetInputLayout(vs1);
            GeometryInputLayout inputLayout2 = cache.GetInputLayout(vs2);

            try {
                cache.GetInputLayout(vs3);
                Assert.Fail();
            }
            catch (InvalidOperationException) { }

            // Assert outcome
            Assert.AreEqual(cache, inputLayout1.AssociatedCache);
            Assert.AreEqual(cache, inputLayout2.AssociatedCache);

            Assert.AreEqual(vs1, inputLayout1.AssociatedShader);
            Assert.AreEqual(vs2, inputLayout2.AssociatedShader);

            KeyValuePair <VertexInputBinding, IVertexBuffer>[] boundCompBuffers = inputLayout1.BoundComponentBuffers;
            Assert.AreEqual(buffers[0], boundCompBuffers.First(kvp => kvp.Key == vs1.GetBindingByIdentifier("POSITION")).Value);
            Assert.IsFalse(boundCompBuffers.Any(kvp => kvp.Value == buffers[1]));

            boundCompBuffers = inputLayout2.BoundComponentBuffers;
            Assert.AreEqual(buffers[0], boundCompBuffers.First(kvp => kvp.Key == vs2.GetBindingByIdentifier("POSITION")).Value);
            Assert.AreEqual(buffers[1], boundCompBuffers.First(kvp => kvp.Key == vs2.GetBindingByIdentifier("RANDOM_FLOATS")).Value);

            Assert.AreEqual(inputLayout1, cache.GetInputLayout(vs1));
            Assert.AreEqual(inputLayout2, cache.GetInputLayout(vs2));

            cache.Dispose();
            inputLayout2.Dispose();
            inputLayout1.Dispose();
            vs1.Dispose();
            vs2.Dispose();
            vs3.Dispose();
            instanceCBuffer.Dispose();
            indices.Dispose();
            buffers[1].Dispose();
            buffers[0].Dispose();
        }
        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 ShouldCookParametersCorrectly()
        {
            // Define variables and constants
            GeometryCacheBuilder <TestVertex> testVertexCacheBuilder = new GeometryCacheBuilder <TestVertex>();
            int cacheID = (int)typeof(GeometryCacheBuilder <TestVertex>).GetField("cacheID", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(testVertexCacheBuilder);

            TestVertex[] model1Verts =
            {
                new TestVertex(Vector3.ONE * 0f, Vector2.ONE * 0f),
                new TestVertex(Vector3.ONE * 1f, Vector2.ONE * 1f),
                new TestVertex(Vector3.ONE * 2f, Vector2.ONE * 2f),
            };
            TestVertex[] model2Verts =
            {
                new TestVertex(Vector3.ONE * 3f, Vector2.ONE * 3f),
                new TestVertex(Vector3.ONE * 4f, Vector2.ONE * 4f),
                new TestVertex(Vector3.ONE * 5f, Vector2.ONE * 5f),
            };

            uint[] model1Indices =
            {
                0U, 1U, 2U,
                1U, 2U, 0U,
                2U, 0U, 1U
            };
            uint[] model2Indices =
            {
                3U, 4U, 5U,
                4U, 5U, 3U,
                5U, 3U, 4U,
                3U, 5U, 4U
            };

            uint outVBStartIndex, outIBStartIndex, outVBCount, outIBCount;

            // Set up context
            Assert.AreEqual(new ModelHandle(cacheID, 0U), testVertexCacheBuilder.AddModel("SCPC_a", model1Verts, model1Indices));
            Assert.AreEqual(new ModelHandle(cacheID, 1U), testVertexCacheBuilder.AddModel("SCPC_b", model2Verts, model2Indices));

            // Execute
            GeometryCache result = testVertexCacheBuilder.Build();

            // Assert outcome
            Assert.AreEqual(cacheID, result.ID);
            Assert.AreEqual(result, GeometryCache.GetCacheByID(cacheID));

            Assert.AreEqual((uint)(model1Indices.Length + model2Indices.Length), result.IndexBuffer.Length);
            Assert.AreEqual((uint)(model1Verts.Length + model2Verts.Length), result.VertexBuffers[0].Length);
            Assert.AreEqual(2, result.VertexBuffers.Count);
            Assert.AreEqual(ResourceFormat.R32G32B32Float, result.VertexFormats[0]);
            Assert.AreEqual(ResourceFormat.R32G32Float, result.VertexFormats[1]);
            Assert.AreEqual(2U, result.NumModels);
            Assert.AreEqual(6U, result.NumVertices);

            Assert.AreEqual(typeof(VertexBuffer <Vector3>), result.VertexBuffers[0].GetType());
            Assert.AreEqual(typeof(VertexBuffer <Vector2>), result.VertexBuffers[1].GetType());

            Assert.AreEqual("POSITION", result.VertexSemantics[0]);
            Assert.AreEqual("TEXCOORD", result.VertexSemantics[1]);

            result.GetModelBufferValues(0U, out outVBStartIndex, out outIBStartIndex, out outVBCount, out outIBCount);

            Assert.AreEqual(0U, outVBStartIndex);
            Assert.AreEqual(0U, outIBStartIndex);
            Assert.AreEqual(3U, outVBCount);
            Assert.AreEqual(9U, outIBCount);

            result.GetModelBufferValues(1U, out outVBStartIndex, out outIBStartIndex, out outVBCount, out outIBCount);

            Assert.AreEqual(3U, outVBStartIndex);
            Assert.AreEqual(9U, outIBStartIndex);
            Assert.AreEqual(3U, outVBCount);
            Assert.AreEqual(12U, outIBCount);

#if !DEVELOPMENT && !RELEASE
            try {
                result.GetModelBufferValues(2U, out outVBStartIndex, out outIBStartIndex, out outVBCount, out outIBCount);
                Assert.Fail();
            }
            catch (AssuranceFailedException) { }
#endif

            result.Dispose();
        }