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