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