Exemplo n.º 1
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);
        }
Exemplo n.º 2
0
        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();
        }