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(); }
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(); }