Beispiel #1
0
        void CreateRenderGraph()
        {
            Dependency.Complete();
#if RENDERING_FORCE_DIRECT
            Assert.IsTrue(false, "Obsolete script define RENDERING_FORCE_DIRECT enabled. Use the RenderGraphConfig singleton to configure a render graph");
#endif
            if (!HasSingleton <RenderGraphConfig>())
            {
                Entity eConfig = GetSingletonEntity <DisplayInfo>();
                EntityManager.AddComponentData <RenderGraphConfig>(eConfig, RenderGraphConfig.Default);
            }

            RenderGraphConfig config = GetSingleton <RenderGraphConfig>();
            if (!config.Equals(currentConfig) || eMainViewNode == Entity.Null)
            {
                RenderDebug.LogAlways("RenderGraphConfig changed, building a new render graph!");
                DestroyRenderGraph();
                // we should run the bgfx system here once, so textures are cleaned up and ready for re-use
                currentConfig = config;
                // we only build a default graph if there are no existing nodes - otherwise assume they are already built
                eMainViewNode = BuildRenderGraph();
                CreateScreenToWorldChain(RenderPassType.Opaque, ScreenToWorldId.MainCamera);
                CreateScreenToWorldChain(RenderPassType.Sprites, ScreenToWorldId.Sprites);
                CreateScreenToWorldChain(RenderPassType.UI, ScreenToWorldId.UILayer);
            }

            // build light nodes for lights that have no node associated - need to do this always
            BuildAllLightNodes(eMainViewNode);
        }
        protected override void OnUpdate()
        {
            if (!SceneService.AreStartupScenesLoaded(World))
            {
                return;
            }
#if DEBUG
            var countEntsStart = GetNumEntities();
#endif
            Entity eMainView = FindMainViewNode();
            if (eMainView == Entity.Null)
            {
                // we only build a default graph if there are no existing nodes - otherwise assume they are already built
                RenderDebug.Log("Auto building default render graph");
                eMainView = BuildDefaultRenderGraph(1920, 1080);
            }

            // build light nodes for lights that have no node associated
            BuildAllLightNodes(eMainView);

#if DEBUG
            var countEntsEnd = GetNumEntities();
            if (countEntsEnd != countEntsStart)
            {
                RenderDebug.LogFormatAlways("Render graph builder added entities (was {0}, now {1})", countEntsStart, countEntsEnd);
            }
#endif
            //Disable Render graph builder system. We need to create it only once
            Enabled = false;
        }
        public static unsafe bool SubmitTransientAlloc(RendererBGFXInstance *sys, bgfx.TransientIndexBuffer *tib, bgfx.TransientVertexBuffer *tvb, int nvertices, int nindices, bgfx.VertexLayout *layout)
        {
            if (!bgfx.alloc_transient_buffers(tvb, layout, (uint)nvertices, tib, (uint)nindices))
            {
#if DEBUG
                // TODO: throw or ignore draw?
                throw new InvalidOperationException("Out of transient bgfx memory!");
#else
                RenderDebug.LogFormat("Warning: Out of transient bgfx memory! Skipping draw call.");
                return(false);
#endif
            }
            return(true);
        }
Beispiel #4
0
        void BuildAllLightNodes(Entity eNodeOutput)
        {
            Assert.IsTrue(EntityManager.HasComponent <RenderNode>(eNodeOutput));
            // go through all lights and create nodes
            Entities.WithoutBurst().WithStructuralChanges().ForEach((Entity eLight, ref Light l, ref ShadowmappedLight sl) => {
                if (sl.shadowMapRenderNode == Entity.Null)
                {
                    // need a node
                    Entity eNode           = CreateNodeEntity();
                    sl.shadowMapRenderNode = eNode;
                    EntityManager.AddComponent <RenderNode>(eNode);

                    if (EntityManager.HasComponent <CascadeShadowmappedLight>(eLight))
                    {
                        // need four passes in node
                        for (int i = 0; i < 4; i++)
                        {
                            Entity ePass = EntityManager.CreateEntity();
                            AddShadowMapPass(eNode, ePass, eLight, i, sl.shadowMapResolution);
                        }
                    }
                    else
                    {
                        Entity ePass = eNode; //why not stick everything on the same entity
                        AddShadowMapPass(eNode, ePass, eLight, -1, sl.shadowMapResolution);
                    }
                    EntityManager.AddComponentData(eNode, new RenderNodeShadowMap {
                        lightsource = eLight
                    });
                    LinkNodes(eNodeOutput, eNode);
                    RenderDebug.LogFormat("Build shadow map node {0}*{0}, input to {1}", sl.shadowMapResolution, eNodeOutput);
                    World.TinyEnvironment().SetEntityName(eNode, "Auto generated: Shadow Map");
                }

                // allocate the texture if needed
                if (sl.shadowMap == Entity.Null)
                {
                    AddRenderToShadowMapForNode(sl.shadowMapRenderNode, sl.shadowMapResolution);
                    var rtt      = EntityManager.GetComponentData <RenderNodeTexture>(sl.shadowMapRenderNode);
                    sl.shadowMap = rtt.depthTexture;
                    Assert.IsTrue(sl.shadowMap != Entity.Null);
                }
            }).Run();
        }
        protected override void OnUpdate()
        {
            var bgfxinst = World.GetExistingSystem <RendererBGFXSystem>().InstancePointer();

            if (!bgfxinst->m_initialized)
            {
                return;
            }

            // setup bgfx side
            Entities.WithoutBurst().ForEach((Entity e, ref RenderPass pass) =>
            {
                if (pass.viewId == 0xffff)
                {
                    RenderDebug.LogFormat("Render pass entity {0} on render node entity {1} is not referenced by the render graph. It should be deleted.", e, pass.inNode);
                    Assert.IsTrue(false);
                    return;
                }
                bool rtt = EntityManager.HasComponent <FramebufferBGFX>(pass.inNode);
                if (rtt)
                {
                    pass.passFlags = RenderPassFlags.RenderToTexture;
                }
                else
                {
                    pass.passFlags = 0;
                }
                // those could be more shared ... (that is, do all passes really need a copy of view & projection?)
                unsafe { fixed(float4x4 * viewp = &pass.viewTransform, projp = &pass.projectionTransform)
                         {
                             if (bgfxinst->m_homogeneousDepth && bgfxinst->m_originBottomLeft) // gl style
                             {
                                 bgfx.set_view_transform(pass.viewId, viewp, projp);
                                 pass.passFlags &= ~RenderPassFlags.FlipCulling;
                             }
                             else // dx style
                             {
                                 bool yflip = !bgfxinst->m_originBottomLeft && rtt;
                                 float4x4 adjustedProjection = RendererBGFXStatic.AdjustProjection(ref pass.projectionTransform, !bgfxinst->m_homogeneousDepth, yflip);
                                 bgfx.set_view_transform(pass.viewId, viewp, &adjustedProjection);
                                 if (yflip)
                                 {
                                     pass.passFlags |= RenderPassFlags.FlipCulling;
                                 }
                                 else
                                 {
                                     pass.passFlags &= ~RenderPassFlags.FlipCulling;
                                 }
                             }
                             // make a viewProjection
                             pass.viewProjectionTransform = math.mul(pass.projectionTransform, pass.viewTransform);
                         } }
                bgfx.set_view_mode(pass.viewId, (bgfx.ViewMode)pass.sorting);
                bgfx.set_view_rect(pass.viewId, pass.viewport.x, pass.viewport.y, pass.viewport.w, pass.viewport.h);
                bgfx.set_view_scissor(pass.viewId, pass.scissor.x, pass.scissor.y, pass.scissor.w, pass.scissor.h);
                bgfx.set_view_clear(pass.viewId, (ushort)pass.clearFlags, pass.clearRGBA, pass.clearDepth, pass.clearStencil);
                if (rtt)
                {
                    var rttbgfx = EntityManager.GetComponentData <FramebufferBGFX>(pass.inNode);
                    bgfx.set_view_frame_buffer(pass.viewId, rttbgfx.handle);
                }
                else
                {
                    bgfx.set_view_frame_buffer(pass.viewId, new bgfx.FrameBufferHandle {
                        idx = 0xffff
                    });
                }
                // touch it? needed?
                bgfx.touch(pass.viewId);
            }).Run();
        }
Beispiel #6
0
        protected override void OnUpdate()
        {
            var bgfxsys = World.GetExistingSystem <RendererBGFXSystem>();

            if (!bgfxsys.Initialized)
            {
                return;
            }

            // make sure passes have viewid, transform, scissor rect and view rect set

            // reset alreadyAdded state
            // we expect < 100 or so passes, so the below code does not need to be crazy great
            Entities.ForEach((ref RenderNode rnode) => { rnode.alreadyAdded = false; });
            Entities.ForEach((ref RenderPass pass) => { pass.viewId = 0xffff; }); // there SHOULD not be any passes around that are not referenced by the graph...

            // get all nodes, sort (bgfx issues in-order per view. a better api could use the render graph to issue without gpu
            // barriers where possible)
            // sort into eval order, assign pass viewId
            ushort nextViewId = 0;

            Entities.WithAll <RenderNodePrimarySurface>().ForEach((Entity eNode) => { RecAddPasses(eNode, ref nextViewId); });

            Entities.WithAll <RenderPassAutoSizeToNode>().ForEach((Entity e, ref RenderPass pass) =>
            {
                if (EntityManager.HasComponent <RenderNodePrimarySurface>(pass.inNode))
                {
                    var di          = World.TinyEnvironment().GetConfigData <DisplayInfo>();
                    pass.viewport.x = 0;
                    pass.viewport.y = 0;
                    pass.viewport.w = (ushort)di.width;
                    pass.viewport.h = (ushort)di.height;
                    return;
                }
                if (EntityManager.HasComponent <RenderNodeTexture>(pass.inNode))
                {
                    var texRef    = EntityManager.GetComponentData <RenderNodeTexture>(pass.inNode);
                    pass.viewport = texRef.rect;
                }
                // TODO: add others like cubemap
            });

            // auto update passes that are matched with a camera
            Entities.ForEach((Entity e, ref RenderPass pass, ref RenderPassUpdateFromCamera fromCam) =>
            {
                Entity eCam              = fromCam.camera;
                CameraMatrices camData   = EntityManager.GetComponentData <CameraMatrices>(eCam);
                pass.viewTransform       = camData.view;
                pass.projectionTransform = camData.projection;
                if (EntityManager.HasComponent <Frustum>(eCam))
                {
                    if (EntityManager.HasComponent <Frustum>(e))
                    {
                        EntityManager.SetComponentData(e, EntityManager.GetComponentData <Frustum>(eCam));
                    }
                }
                else
                {
                    if (EntityManager.HasComponent <Frustum>(e))
                    {
                        EntityManager.SetComponentData(e, new Frustum());
                    }
                }
            });

            // auto update passes that are matched with a light
            Entities.ForEach((Entity e, ref RenderPass pass, ref RenderPassUpdateFromLight fromLight) =>
            {
                Entity eLight            = fromLight.light;
                LightMatrices lightData  = EntityManager.GetComponentData <LightMatrices>(eLight);
                pass.viewTransform       = lightData.view;
                pass.projectionTransform = lightData.projection;
                if (EntityManager.HasComponent <Frustum>(eLight))
                {
                    if (EntityManager.HasComponent <Frustum>(e))
                    {
                        EntityManager.SetComponentData(e, EntityManager.GetComponentData <Frustum>(eLight));
                    }
                }
                else
                {
                    if (EntityManager.HasComponent <Frustum>(e))
                    {
                        EntityManager.SetComponentData(e, new Frustum());
                    }
                }
            });

            // set up extra pass data
            Entities.ForEach((Entity e, ref RenderPass pass) =>
            {
                if (pass.viewId == 0xffff)
                {
                    RenderDebug.LogFormat("Render pass entity {0} on render node entity {1} is not referenced by the render graph. It should be deleted.", e, pass.inNode);
                    Assert.IsTrue(false);
                    return;
                }
                bool rtt = EntityManager.HasComponent <FramebufferBGFX>(pass.inNode);
                // those could be more shared ... (that is, do all passes really need a copy of view & projection?)
                unsafe { fixed(float4x4 * viewp = &pass.viewTransform, projp = &pass.projectionTransform)
                         {
                             if (bgfxsys.m_homogeneousDepth && bgfxsys.m_originBottomLeft) // gl style
                             {
                                 bgfx.set_view_transform(pass.viewId, viewp, projp);
                                 pass.flipCulling = 0;
                             }
                             else // dx style
                             {
                                 bool yflip = !bgfxsys.m_originBottomLeft && rtt;
                                 float4x4 adjustedProjection = RendererBGFXSystem.AdjustProjection(ref pass.projectionTransform, !bgfxsys.m_homogeneousDepth, yflip);
                                 bgfx.set_view_transform(pass.viewId, viewp, &adjustedProjection);
                                 pass.flipCulling = yflip ? (byte)3 : (byte)0;
                             }
                         } }
                bgfx.set_view_mode(pass.viewId, (bgfx.ViewMode)pass.sorting);
                bgfx.set_view_rect(pass.viewId, pass.viewport.x, pass.viewport.y, pass.viewport.w, pass.viewport.h);
                bgfx.set_view_scissor(pass.viewId, pass.scissor.x, pass.scissor.y, pass.scissor.w, pass.scissor.h);
                bgfx.set_view_clear(pass.viewId, (ushort)pass.clearFlags, pass.clearRGBA, pass.clearDepth, pass.clearStencil);
                if (rtt)
                {
                    var rttbgfx = EntityManager.GetComponentData <FramebufferBGFX>(pass.inNode);
                    bgfx.set_view_frame_buffer(pass.viewId, rttbgfx.handle);
                }
                else
                {
                    bgfx.set_view_frame_buffer(pass.viewId, new bgfx.FrameBufferHandle {
                        idx = 0xffff
                    });
                }
                // touch it? needed?
                bgfx.touch(pass.viewId);
            });
        }
        protected override void OnUpdate()
        {
            if (!SceneService.AreStartupScenesLoaded(World))
            {
                return;
            }
#if DEBUG
            var countEntsStart = GetNumEntities();
#endif
            // gather all passes
            var q = GetEntityQuery(ComponentType.ReadOnly <RenderPass>());
            m_allPasses = q.ToEntityArray(Allocator.TempJob);

            // go through lit renderers and assign lighting setup to them
            // create light
            // TEMP HACK
            var    q2        = GetEntityQuery(ComponentType.ReadOnly <LightingBGFX>());
            Entity eLighting = Entity.Null;
            if (q2.CalculateEntityCount() == 0)
            {
                eLighting = EntityManager.CreateEntity();
                EntityManager.AddComponentData(eLighting, new LightingBGFX());
                // add both ways lookup lighting setup <-> light
                var b1 = EntityManager.AddBuffer <LightToBGFXLightingSetup>(eLighting);
                Entities.WithAll <Light>().ForEach((Entity e) =>
                {
                    b1.Add(new LightToBGFXLightingSetup {
                        e = e
                    });
                });
                Entities.WithAll <Light>().ForEach((Entity e) =>
                {
                    var b = EntityManager.AddBuffer <LightToBGFXLightingSetup>(e);
                    b.Add(new LightToBGFXLightingSetup {
                        e = eLighting
                    });
                });
            }
            else
            {
                var a = q2.ToEntityArray(Allocator.TempJob);
                Assert.IsTrue(a.Length == 1);
                eLighting = a[0];
                a.Dispose();
            }
            Entities.WithNone <LightingRef>().ForEach((Entity e, ref MeshRenderer rlmr, ref LitMeshReference meshRef) =>
            {
                OptionalSetSharedComponent(e, new LightingRef {
                    e = eLighting
                });
            });
            // EOH

            m_buildGroups = new NativeHashMap <BuildGroup, Entity>(256, Allocator.TempJob);

            // find existing groups and add them to builder
            Entities.WithAll <RenderGroup>().ForEach((Entity e, ref BuildGroup bg) =>
            {
                m_buildGroups.Add(bg, e);
            });

            // go through all known render types, and assign groups to them
            // assign groups to all renderers
            Entities.WithNone <RenderToPasses>().ForEach((Entity e, ref MeshRenderer rlmr) =>
            {
                bool isTransparent = false;
                if (EntityManager.HasComponent <SimpleMeshReference>(e))
                {
                    if (EntityManager.HasComponent <SimpleMaterial>(rlmr.material))
                    {
                        isTransparent = EntityManager.GetComponentData <SimpleMaterial>(rlmr.material).transparent;
                    }
                    else if (EntityManager.HasComponent <SimpleMaterialBGFX>(rlmr.material))
                    {
                        var matBGFX   = EntityManager.GetComponentData <SimpleMaterialBGFX>(rlmr.material);
                        isTransparent = (matBGFX.state & (ulong)bgfx.StateFlags.WriteZ) != (ulong)bgfx.StateFlags.WriteZ;
                    }
                }
                else if (EntityManager.HasComponent <LitMeshReference>(e))
                {
                    if (EntityManager.HasComponent <LitMaterial>(rlmr.material))
                    {
                        isTransparent = EntityManager.GetComponentData <LitMaterial>(rlmr.material).transparent;
                    }
                    else if (EntityManager.HasComponent <LitMaterialBGFX>(rlmr.material))
                    {
                        var matBGFX   = EntityManager.GetComponentData <LitMaterialBGFX>(rlmr.material);
                        isTransparent = (matBGFX.state & (ulong)bgfx.StateFlags.WriteZ) != (ulong)bgfx.StateFlags.WriteZ;
                    }
                }

                CameraMask cameraMask = new CameraMask {
                    mask = ulong.MaxValue
                };
                if (EntityManager.HasComponent <CameraMask>(e))
                {
                    cameraMask = EntityManager.GetComponentData <CameraMask>(e);
                }
                ShadowMask shadowMask = new ShadowMask {
                    mask = ulong.MaxValue
                };
                if (EntityManager.HasComponent <ShadowMask>(e))
                {
                    shadowMask = EntityManager.GetComponentData <ShadowMask>(e);
                }
                Entity eGroup;
                if (isTransparent)
                {
                    eGroup = FindOrCreateRenderGroup(new BuildGroup {
                        passTypes = RenderPassType.Transparent, cameraMask = cameraMask, shadowMask = shadowMask
                    });
                }
                else
                {
                    eGroup = FindOrCreateRenderGroup(new BuildGroup {
                        passTypes = RenderPassType.Opaque | RenderPassType.ZOnly | RenderPassType.ShadowMap, cameraMask = cameraMask, shadowMask = shadowMask
                    });
                }

                OptionalSetSharedComponent(e, new RenderToPasses {
                    e = eGroup
                });
            });

            Entities.WithNone <RenderToPasses>().ForEach((Entity e, ref GizmoLight rlgmr) =>
            {
                ShadowMask shadowMask = new ShadowMask {
                    mask = ulong.MaxValue
                };
                CameraMask cameraMask = new CameraMask {
                    mask = 0
                };
                Entity eGroup = FindOrCreateRenderGroup(new BuildGroup {
                    passTypes = RenderPassType.Transparent, cameraMask = cameraMask, shadowMask = shadowMask
                });
                OptionalSetSharedComponent(e, new RenderToPasses {
                    e = eGroup
                });
            });


            m_buildGroups.Dispose();
            m_allPasses.Dispose();

            // TODO: remove any passes that are not referenced by anything

#if DEBUG
            var countEntsEnd = GetNumEntities();
            if (countEntsEnd != countEntsStart)
            {
                RenderDebug.LogFormatAlways("Render graph builder added entities (was {0}, now {1})", countEntsStart, countEntsEnd);
            }
#endif
        }
        protected void BuildAllLightNodes(Entity eNodeOutput)
        {
            Assert.IsTrue(EntityManager.HasComponent <RenderNode>(eNodeOutput));
            // go through all lights and create nodes
            Entities.ForEach((Entity eLight, ref Light l, ref ShadowmappedLight sl) =>
            {
                if (sl.shadowMapRenderNode == Entity.Null)
                {
                    // need a node, with a pass
                    Entity eNode = CreateNodeEntity();
                    EntityManager.AddComponent <RenderNode>(eNode);
                    Entity ePass = eNode; //why not stick everything on the same entity! EntityManager.CreateEntity();
                    EntityManager.AddComponentData(ePass, new RenderPass
                    {
                        inNode              = eNode,
                        sorting             = RenderPassSort.Unsorted,
                        projectionTransform = float4x4.identity,
                        viewTransform       = float4x4.identity,
                        passType            = RenderPassType.ShadowMap,
                        viewId              = 0xffff,
                        scissor             = new RenderPassRect {
                            x = 0, y = 0, w = 0, h = 0
                        },
                        viewport = new RenderPassRect {
                            x = 0, y = 0, w = (ushort)sl.shadowMapResolution, h = (ushort)sl.shadowMapResolution
                        },
#if SAFARI_WEBGL_WORKAROUND
                        clearFlags = RenderPassClear.Depth | RenderPassClear.Color,
#else
                        clearFlags = RenderPassClear.Depth,
#endif
                        clearRGBA    = 0,
                        clearDepth   = 1,
                        clearStencil = 0
                    });
                    EntityManager.AddComponentData(ePass, new RenderPassUpdateFromLight
                    {
                        light = eLight
                    });
                    EntityManager.AddComponentData(eNode, new RenderNodeShadowMap
                    {
                        lightsource = eLight,
                    });
                    sl.shadowMapRenderNode = eNode;
                    EntityManager.GetBuffer <RenderPassRef>(eNode).Add(new RenderPassRef {
                        e = ePass
                    });

                    LinkNodes(eNodeOutput, eNode);
                    RenderDebug.LogFormat("Build shadow map node {0}*{0}, input to {1}", sl.shadowMapResolution, eNodeOutput);
                    World.TinyEnvironment().SetEntityName(eNode, "Auto generated: Shadow Map");
                }
                if (sl.shadowMap == Entity.Null)
                {
                    AddRenderToShadowMapForNode(sl.shadowMapRenderNode, sl.shadowMapResolution, sl.shadowMapResolution);
                    var rtt      = EntityManager.GetComponentData <RenderNodeTexture>(sl.shadowMapRenderNode);
                    sl.shadowMap = rtt.depthTexture;
                    Assert.IsTrue(sl.shadowMap != Entity.Null);
                }
            });
        }