public override void PrepareEffectPermutations(RenderDrawContext context)
        {
            base.PrepareEffectPermutations(context);

            var rootEffectRenderFeature = ((RootEffectRenderFeature)RootRenderFeature);
            var renderEffects           = RootRenderFeature.RenderData.GetData(((RootEffectRenderFeature)RootRenderFeature).RenderEffectKey);
            int effectSlotCount         = ((RootEffectRenderFeature)RootRenderFeature).EffectPermutationSlotCount;

            Dispatcher.ForEach(RootRenderFeature.ObjectNodeReferences, objectNodeReference =>
            {
                var objectNode       = RootRenderFeature.GetObjectNode(objectNodeReference);
                var renderMesh       = (RenderMesh)objectNode.RenderObject;
                var staticObjectNode = renderMesh.StaticObjectNode;

                renderMesh.ActiveMeshDraw = renderMesh.Mesh.Draw;

                foreach (var stage in RenderSystem.RenderStages)
                {
                    if (stage == null)
                    {
                        continue;
                    }
                    var effectSlot             = rootEffectRenderFeature.GetEffectPermutationSlot(stage);
                    var staticEffectObjectNode = staticObjectNode * effectSlotCount + effectSlot.Index;
                    var renderEffect           = renderEffects[staticEffectObjectNode];

                    if (renderEffect != null)
                    {
                        renderEffect.EffectValidator.ValidateParameterThreaded(XenkoEffectBaseKeys.ComputeVelocityShader, new ShaderClassSource("MeshVelocity"));
                    }
                }
            });
        }
示例#2
0
        /// <inheritdoc/>
        public override void Extract()
        {
            var renderModelObjectInfo = RootRenderFeature.RenderData.GetData(RenderModelObjectInfoKey);

            //for (int index = 0; index < RootRenderFeature.ObjectNodeReferences.Count; index++)
            Dispatcher.For(0, RootRenderFeature.ObjectNodeReferences.Count, index =>
            {
                var objectNodeReference = RootRenderFeature.ObjectNodeReferences[index];
                var objectNode          = RootRenderFeature.GetObjectNode(objectNodeReference);
                var renderMesh          = objectNode.RenderObject as RenderMesh;

                // TODO: Extract world
                renderModelObjectInfo[objectNodeReference].World = renderMesh != null ? renderMesh.World : Matrix.Identity;
            });
        }
示例#3
0
        /// <param name="context"></param>
        /// <inheritdoc/>
        public override void PrepareEffectPermutations(RenderDrawContext context)
        {
            var skinningInfos = RootRenderFeature.RenderData.GetData(skinningInfoKey);

            var renderEffects   = RootRenderFeature.RenderData.GetData(renderEffectKey);
            int effectSlotCount = ((RootEffectRenderFeature)RootRenderFeature).EffectPermutationSlotCount;

            //foreach (var objectNodeReference in RootRenderFeature.ObjectNodeReferences)
            Dispatcher.ForEach(((RootEffectRenderFeature)RootRenderFeature).ObjectNodeReferences, objectNodeReference =>
            {
                var objectNode       = RootRenderFeature.GetObjectNode(objectNodeReference);
                var renderMesh       = (RenderMesh)objectNode.RenderObject;
                var staticObjectNode = renderMesh.StaticObjectNode;

                ref var skinningInfo = ref skinningInfos[staticObjectNode];
                var parameters       = renderMesh.Mesh.Parameters;
                if (parameters != skinningInfo.Parameters || parameters.PermutationCounter != skinningInfo.PermutationCounter)
                {
                    skinningInfo.Parameters         = parameters;
                    skinningInfo.PermutationCounter = parameters.PermutationCounter;

                    skinningInfo.HasSkinningPosition = parameters.Get(MaterialKeys.HasSkinningPosition);
                    skinningInfo.HasSkinningNormal   = parameters.Get(MaterialKeys.HasSkinningNormal);
                    skinningInfo.HasSkinningTangent  = parameters.Get(MaterialKeys.HasSkinningTangent);
                }

                for (int i = 0; i < effectSlotCount; ++i)
                {
                    var staticEffectObjectNode = staticObjectNode * effectSlotCount + i;
                    var renderEffect           = renderEffects[staticEffectObjectNode];

                    // Skip effects not used during this frame
                    if (renderEffect == null || !renderEffect.IsUsedDuringThisFrame(RenderSystem))
                    {
                        continue;
                    }

                    if (renderMesh.Mesh.Skinning != null)
                    {
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.HasSkinningPosition, skinningInfo.HasSkinningPosition);
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.HasSkinningNormal, skinningInfo.HasSkinningNormal);
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.HasSkinningTangent, skinningInfo.HasSkinningTangent);

                        var skinningBones = Math.Max(MaxBones, renderMesh.Mesh.Skinning.Bones.Length);
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.SkinningMaxBones, skinningBones);
                    }
                }
            });
示例#4
0
        /// <param name="context"></param>
        /// <inheritdoc/>
        public override unsafe void Prepare(RenderDrawContext context)
        {
            // Compute WorldView, WorldViewProj
            var renderModelObjectInfoData = RootRenderFeature.RenderData.GetData(RenderModelObjectInfoKey);
            var renderModelViewInfoData   = RootRenderFeature.RenderData.GetData(RenderModelViewInfoKey);

            // Update PerFrame (time)
            // TODO Move that to RootEffectRenderFeature?
            float timeStep = (float)Context.Time.Elapsed.TotalSeconds * GlobalKeys.TimeScale;

            scaledTimeAccumulator += timeStep;
            foreach (var frameLayout in ((RootEffectRenderFeature)RootRenderFeature).FrameLayouts)
            {
                var timeOffset = frameLayout.GetConstantBufferOffset(time);
                if (timeOffset == -1)
                {
                    continue;
                }

                var resourceGroup = frameLayout.Entry.Resources;
                var mappedCB      = resourceGroup.ConstantBuffer.Data;

                var perFrameTime = (PerFrameTime *)((byte *)mappedCB + timeOffset);
                perFrameTime->TimeStep = timeStep;
                perFrameTime->Time     = scaledTimeAccumulator;
            }

            // Update PerView (View, Proj, etc...)
            for (int index = 0; index < RenderSystem.Views.Count; index++)
            {
                var view        = RenderSystem.Views[index];
                var viewFeature = view.Features[RootRenderFeature.Index];

                // Compute WorldView and WorldViewProjection
                Dispatcher.ForEach(viewFeature.ViewObjectNodes, renderPerViewNodeReference =>
                {
                    var renderPerViewNode        = RootRenderFeature.GetViewObjectNode(renderPerViewNodeReference);
                    ref var renderModelFrameInfo = ref renderModelObjectInfoData[renderPerViewNode.ObjectNode];
                    ref var renderModelViewInfo  = ref renderModelViewInfoData[renderPerViewNodeReference];

                    Matrix.Multiply(ref renderModelFrameInfo.World, ref view.View, out renderModelViewInfo.WorldView);
                    Matrix.Multiply(ref renderModelFrameInfo.World, ref view.ViewProjection, out renderModelViewInfo.WorldViewProjection);
                });
示例#5
0
 /// <summary>
 /// Attach this <see cref="SubRenderFeature"/> to a <see cref="RootRenderFeature"/>.
 /// </summary>
 /// <param name="rootRenderFeature"></param>
 internal void AttachRootRenderFeature(RootRenderFeature rootRenderFeature)
 {
     this.RootRenderFeature = rootRenderFeature;
     RenderSystem           = rootRenderFeature.RenderSystem;
 }
        public override unsafe void Prepare(RenderDrawContext context)
        {
            var previousTransformationInfoData     = RootRenderFeature.RenderData.GetData(previousTransformationInfoKey);
            var previousTransformationViewInfoData = RootRenderFeature.RenderData.GetData(previousTransformationViewInfoKey);
            var renderModelObjectInfoData          = RootRenderFeature.RenderData.GetData(renderModelObjectInfoKey);

            // Calculate previous WVP matrix per view and object
            usageCounter++;
            for (int index = 0; index < RenderSystem.Views.Count; index++)
            {
                var view        = RenderSystem.Views[index];
                var viewFeature = view.Features[RootRenderFeature.Index];

                bool useView = false;
                foreach (var stage in RenderSystem.RenderStages)
                {
                    foreach (var renderViewStage in view.RenderStages)
                    {
                        if (renderViewStage.Index == stage.Index && stage.OutputValidator?.Find <VelocityTargetSemantic>() >= 0)
                        {
                            useView = true;
                            break;
                        }
                    }
                }
                if (!useView)
                {
                    continue;
                }

                // Cache per-view data locally
                RenderViewData viewData;
                if (!renderViewDatas.TryGetValue(view, out viewData))
                {
                    viewData = new RenderViewData();
                    renderViewDatas.Add(view, viewData);
                }

                Dispatcher.ForEach(viewFeature.ViewObjectNodes, renderPerViewNodeReference =>
                {
                    var renderPerViewNode    = RootRenderFeature.GetViewObjectNode(renderPerViewNodeReference);
                    var renderModelFrameInfo = renderModelObjectInfoData[renderPerViewNode.ObjectNode];

                    Matrix previousViewProjection = viewData.PreviousViewProjection;

                    Matrix previousWorldViewProjection;
                    Matrix.Multiply(ref renderModelFrameInfo.World, ref previousViewProjection, out previousWorldViewProjection);

                    previousTransformationViewInfoData[renderPerViewNodeReference] = new PreviousObjectViewInfo
                    {
                        WorldViewProjection = previousWorldViewProjection,
                    };
                });

                // Shift current view projection transform into previous
                viewData.PreviousViewProjection = view.ViewProjection;
                viewData.UsageCounter           = usageCounter;
                updatedViews.Add(view);
            }

            foreach (var view in renderViewDatas.Keys.ToArray())
            {
                if (!updatedViews.Contains(view))
                {
                    renderViewDatas.Remove(view);
                }
            }
            updatedViews.Clear();

            // Update cbuffer for previous WVP matrix
            Dispatcher.ForEach(((RootEffectRenderFeature)RootRenderFeature).RenderNodes, (ref RenderNode renderNode) =>
            {
                var perDrawLayout = renderNode.RenderEffect?.Reflection?.PerDrawLayout;
                if (perDrawLayout == null)
                {
                    return;
                }

                var previousWvpOffset = perDrawLayout.GetConstantBufferOffset(previousWorldViewProjection);
                if (previousWvpOffset == -1)
                {
                    return;
                }

                var mappedCB        = renderNode.Resources.ConstantBuffer.Data;
                var previousPerDraw = (PreviousPerDraw *)((byte *)mappedCB + previousWvpOffset);

                var renderModelFrameInfo         = renderModelObjectInfoData[renderNode.RenderObject.ObjectNode];
                var renderModelPreviousFrameInfo = previousTransformationViewInfoData[renderNode.ViewObjectNode];

                // Shift current world transform into previous transform
                previousTransformationInfoData[renderNode.RenderObject.StaticObjectNode] = new StaticObjectInfo
                {
                    World = renderModelFrameInfo.World,
                };

                previousPerDraw->PreviousWorldViewProjection = renderModelPreviousFrameInfo.WorldViewProjection;
            });
        }
 public RenderNodeFeatureReference(RootRenderFeature rootRenderFeature, RenderNodeReference renderNode, RenderObject renderObject)
 {
     RootRenderFeature = rootRenderFeature;
     RenderNode        = renderNode;
     RenderObject      = renderObject;
 }
示例#8
0
        /// <summary>
        /// Performs most of the work (computation and resource preparation). Later game simulation might be running during that step.
        /// </summary>
        /// <param name="context"></param>
        public unsafe void Prepare(RenderDrawContext context)
        {
            // Sync point: after extract, before prepare (game simulation could resume now)

            // Split up Prepare Effects
            Dispatcher.For(0, RenderFeatures.Count, i => {
                // Divide into task chunks for parallelism
                RootRenderFeature renderFeature = RenderFeatures[i];
                renderFeature.PrepareEffectPermutations(context);
            });

            // split up Prepares
            Dispatcher.For(0, RenderFeatures.Count, i => {
                // Divide into task chunks for parallelism
                RootRenderFeature renderFeature = RenderFeatures[i];
                renderFeature.Prepare(context);
            });

            // Sort
            Dispatcher.ForEach(Views, view =>
            {
                Dispatcher.For(0, view.RenderStages.Count, () => prepareThreadLocals.Acquire(), (index, local) =>
                {
                    var renderViewStage = view.RenderStages[index];

                    var renderNodes = renderViewStage.RenderNodes;
                    if (renderNodes.Count == 0)
                    {
                        return;
                    }

                    var renderStage       = RenderStages[renderViewStage.Index];
                    var sortedRenderNodes = renderViewStage.SortedRenderNodes;

                    // Fast clear, since it's cleared properly in Reset()
                    sortedRenderNodes.Resize(renderViewStage.RenderNodes.Count, true);

                    if (renderStage.SortMode != null)
                    {
                        // Make sure sortKeys is big enough
                        if (local.SortKeys == null || local.SortKeys.Length < renderNodes.Count)
                        {
                            Array.Resize(ref local.SortKeys, renderNodes.Count);
                        }

                        // renderNodes[start..end] belongs to the same render feature
                        fixed(SortKey * sortKeysPtr = local.SortKeys)
                        renderStage.SortMode.GenerateSortKey(view, renderViewStage, sortKeysPtr);

                        Dispatcher.Sort(local.SortKeys, 0, renderNodes.Count, Comparer <SortKey> .Default);

                        // Reorder list
                        for (int i = 0; i < renderNodes.Count; ++i)
                        {
                            sortedRenderNodes[i] = renderNodes[local.SortKeys[i].Index];
                        }
                    }
                    else
                    {
                        // No sorting, copy as is
                        for (int i = 0; i < renderNodes.Count; ++i)
                        {
                            sortedRenderNodes[i] = renderNodes[i];
                        }
                    }
                }, state => prepareThreadLocals.Release(state));
            });

            // Flush the resources uploaded during Prepare
            context.ResourceGroupAllocator.Flush();
            context.RenderContext.Flush();
        }