protected override void RecordCommandsInternal(ref MyRenderableProxy_2 proxy, int instanceIndex, int sectionIndex) { MyRenderUtils.SetSrvs(RC, ref proxy.ObjectSrvs); Stats.Draws++; if (instanceIndex == -1) { MyRenderUtils.BindShaderBundle(RC, proxy.HighlightShaders.MultiInstance); for (int it = 0; it < proxy.Submeshes.Length; it++) { MyDrawSubmesh_2 submesh = proxy.Submeshes[it]; DrawSubmesh(ref proxy, ref submesh, sectionIndex); } } else { MyRenderUtils.BindShaderBundle(RC, proxy.HighlightShaders.SingleInstance); MyDrawSubmesh_2 submesh; if (sectionIndex == -1) { submesh = proxy.Submeshes[instanceIndex]; } else { submesh = proxy.SectionSubmeshes[instanceIndex][sectionIndex]; } DrawSubmesh(ref proxy, ref submesh, instanceIndex); } }
protected override void RecordCommandsInternal(ref MyRenderableProxy_2 proxy, int instanceIndex, int sectionIndex) { RC.SetSRVs(ref proxy.ObjectSRVs); RC.BindVertexData(ref proxy.VertexData); Stats.Meshes++; if (instanceIndex == -1) { RC.BindShaders(proxy.HighlightShaders.MultiInstance); for (int it = 0; it < proxy.Submeshes.Length; it++) { MyDrawSubmesh_2 submesh = proxy.Submeshes[it]; DrawSubmesh(ref proxy, ref submesh, sectionIndex); } } else { RC.BindShaders(proxy.HighlightShaders.SingleInstance); MyDrawSubmesh_2 submesh; if (sectionIndex == -1) { submesh = proxy.Submeshes[instanceIndex]; } else { submesh = proxy.SectionSubmeshes[instanceIndex][sectionIndex]; } DrawSubmesh(ref proxy, ref submesh, instanceIndex); } }
internal void UpdateProxySectionSubmeshes(ref MyRenderableProxy_2 proxy) { int filledSize; MyInstanceEntityInfo[] infos = m_mergeGroup.GetEntityInfos(out filledSize); // NB: It's important here to keep SectionSubmeshes same fill size as the // merge group instances, keeping also the holes. In this way, indexing // is kept consistent with the shader and we don't need other indirections proxy.SectionSubmeshes = new MyDrawSubmesh_2[filledSize][]; m_actorIndices.Clear(); int actorIndex = 0; for (int it = 0; it < filledSize; it++) { MyInstanceEntityInfo info = infos[it]; if (info.EntityId.HasValue) { MyActor actor = m_actors[info.EntityId.Value]; int indexOffset = info.PageOffset * m_mergeGroup.TablePageSize; UpdateActorSubmeshes(ref proxy, actor, actorIndex, indexOffset); m_actorIndices[actor] = actorIndex; } actorIndex++; } }
internal void BuildProxy(out MyRenderableProxy_2 proxy, out UInt64 key) { var material = MyMeshMaterials1.GetProxyId(MyMeshMaterials1.MaterialRkIndex.Get(m_rootMaterialRK, MyMeshMaterialId.NULL)); proxy = new MyRenderableProxy_2 { MaterialType = MyMaterialType.OPAQUE, ObjectConstants = new MyConstantsPack { }, ObjectSrvs = new MySrvTable { StartSlot = MyCommon.INSTANCE_INDIRECTION, Srvs = m_mergeGroup.m_srvs, BindFlag = MyBindFlag.BIND_VS, Version = this.GetHashCode() }, DepthShaders = GetMergeInstancing(X.TEXT_(MyMaterialShaders.DEPTH_PASS), MyShaderUnifiedFlags.DEPTH_ONLY), HighlightShaders = GetMergeInstancing(X.TEXT_(MyMaterialShaders.HIGHLIGHT_PASS)), Shaders = GetMergeInstancing(X.TEXT_(MyMaterialShaders.GBUFFER_PASS)), ForwardShaders = GetMergeInstancing(X.TEXT_(MyMaterialShaders.FORWARD_PASS), MyShaderUnifiedFlags.USE_SHADOW_CASCADES), RenderFlags = MyRenderableProxyFlags.DepthSkipTextures, Submeshes = new MyDrawSubmesh_2[] { new MyDrawSubmesh_2 { DrawCommand = MyDrawCommandEnum.Draw, Count = m_mergeGroup.VerticesNum, MaterialId = material } }, SubmeshesDepthOnly = new MyDrawSubmesh_2[] { new MyDrawSubmesh_2 { DrawCommand = MyDrawCommandEnum.Draw, Count = m_mergeGroup.VerticesNum, MaterialId = material } }, InstanceCount = 0, StartInstance = 0, }; key = 0; }
internal void BuildProxy(out MyRenderableProxy_2 proxy, out UInt64 key) { proxy = new MyRenderableProxy_2 { MaterialType = MyMaterialType.OPAQUE, ObjectConstants = new MyConstantsPack { }, ObjectSRVs = new MySrvTable { StartSlot = MyCommon.INSTANCE_INDIRECTION, SRVs = m_mergeGroup.m_SRVs, BindFlag = MyBindFlag.BIND_VS, Version = this.GetHashCode() }, VertexData = new MyVertexDataProxy_2 { }, DepthShaders = MyMaterialShaders.Get(X.TEXT("standard"), X.TEXT(MyGeometryRenderer.DEFAULT_DEPTH_PASS), MyVertexLayouts.Empty, MyShaderUnifiedFlags.USE_MERGE_INSTANCING | MyShaderUnifiedFlags.DEPTH_ONLY), Shaders = MyMaterialShaders.Get(X.TEXT("standard"), X.TEXT(MyGeometryRenderer.DEFAULT_OPAQUE_PASS), MyVertexLayouts.Empty, MyShaderUnifiedFlags.USE_MERGE_INSTANCING), ForwardShaders = MyMaterialShaders.Get(X.TEXT("standard"), X.TEXT(MyGeometryRenderer.DEFAULT_FORWARD_PASS), MyVertexLayouts.Empty, MyShaderUnifiedFlags.USE_MERGE_INSTANCING | MyShaderUnifiedFlags.USE_SHADOW_CASCADES), RenderFlags = MyRenderableProxyFlags.DepthSkipTextures, Submeshes = new MyDrawSubmesh_2[] { new MyDrawSubmesh_2 { DrawCommand = MyDrawCommandEnum.Draw, Count = m_mergeGroup.VerticesNum, MaterialId = MyMeshMaterials1.GetProxyId(MyMeshMaterials1.MaterialRkIndex.Get(m_rootMaterialRK, MyMeshMaterialId.NULL)) } }, SubmeshesDepthOnly = new MyDrawSubmesh_2[] { new MyDrawSubmesh_2 { DrawCommand = MyDrawCommandEnum.Draw, Count = m_mergeGroup.VerticesNum, MaterialId = MyMeshMaterials1.GetProxyId(MyMeshMaterials1.MaterialRkIndex.Get(m_rootMaterialRK, MyMeshMaterialId.NULL)) } }, InstanceCount = 0, StartInstance = 0, }; key = 0; }
protected unsafe void SetProxyConstants(ref MyRenderableProxy_2 proxy, MyMergeInstancingConstants?arg = null) { MyMergeInstancingConstants constants = arg ?? MyMergeInstancingConstants.Default; int version = constants.GetHashCode(); if (constants.GetHashCode() != proxy.ObjectConstants.Version) { int size = sizeof(MyMergeInstancingConstants); var buffer = new byte[sizeof(MyMergeInstancingConstants)]; proxy.ObjectConstants = new MyConstantsPack() { BindFlag = MyBindFlag.BIND_VS, CB = MyCommon.GetObjectCB(size), Version = version, Data = buffer }; fixed(byte *dstPtr = buffer) { #if XB1 SharpDX.Utilities.CopyMemory(new IntPtr(dstPtr), new IntPtr(&constants), size); #else // !XB1 MyMemory.CopyMemory(new IntPtr(dstPtr), new IntPtr(&constants), (uint)size); #endif // !XB1 } } MyRenderUtils.MoveConstants(RC, ref proxy.ObjectConstants); MyRenderUtils.SetConstants(RC, ref proxy.ObjectConstants, MyCommon.OBJECT_SLOT); ++Stats.ObjectConstantsChanges; }
protected override void RecordCommandsInternal(ref MyRenderableProxy_2 proxy, int instanceIndex, int sectionIndex) { RC.SetSRVs(ref proxy.ObjectSRVs); RC.BindVertexData(ref proxy.VertexData); Debug.Assert(proxy.ForwardShaders.MultiInstance.VS != null); RC.BindShaders(proxy.ForwardShaders.MultiInstance); SetProxyConstants(ref proxy); for (int i = 0; i < proxy.Submeshes.Length; i++) { var submesh = proxy.Submeshes[i]; var material = MyMaterials1.ProxyPool.Data[submesh.MaterialId.Index]; RC.MoveConstants(ref material.MaterialConstants); RC.SetConstants(ref material.MaterialConstants, MyCommon.MATERIAL_SLOT); RC.SetSRVs(ref material.MaterialSRVs); if (proxy.InstanceCount == 0) { switch (submesh.DrawCommand) { case MyDrawCommandEnum.DrawIndexed: RC.DeviceContext.DrawIndexed(submesh.Count, submesh.Start, submesh.BaseVertex); break; case MyDrawCommandEnum.Draw: RC.DeviceContext.Draw(submesh.Count, submesh.Start); break; default: break; } } else { switch (submesh.DrawCommand) { case MyDrawCommandEnum.DrawIndexed: //MyRender11.AddDebugQueueMessage("ForwardPass DrawIndexedInstanced " + proxy.VertexData.VB[0].DebugName); RC.DeviceContext.DrawIndexedInstanced(submesh.Count, proxy.InstanceCount, submesh.Start, submesh.BaseVertex, proxy.StartInstance); break; case MyDrawCommandEnum.Draw: RC.DeviceContext.DrawInstanced(submesh.Count, proxy.InstanceCount, submesh.Start, proxy.StartInstance); break; default: break; } } } }
internal override void RecordCommands(ref MyRenderableProxy_2 proxy) { RC.SetSRVs(ref proxy.ObjectSRVs); RC.BindVertexData(ref proxy.VertexData); Debug.Assert(proxy.Shaders.VS != null); RC.BindShaders(proxy.Shaders); for (int i = 0; i < proxy.Submeshes.Length; i++) { var submesh = proxy.Submeshes[i]; var material = MyMaterials1.ProxyPool.Data[submesh.MaterialId.Index]; RC.MoveConstants(ref material.MaterialConstants); RC.SetConstants(ref material.MaterialConstants, MyCommon.MATERIAL_SLOT); RC.SetSRVs(ref material.MaterialSRVs); if (proxy.InstanceCount == 0) { switch (submesh.DrawCommand) { case MyDrawCommandEnum.DrawIndexed: RC.Context.DrawIndexed(submesh.Count, submesh.Start, submesh.BaseVertex); break; case MyDrawCommandEnum.Draw: RC.Context.Draw(submesh.Count, submesh.Start); break; default: break; } } else { switch (submesh.DrawCommand) { case MyDrawCommandEnum.DrawIndexed: RC.Context.DrawIndexedInstanced(submesh.Count, proxy.InstanceCount, submesh.Start, submesh.BaseVertex, proxy.StartInstance); break; case MyDrawCommandEnum.Draw: RC.Context.DrawInstanced(submesh.Count, proxy.InstanceCount, submesh.Start, proxy.StartInstance); break; default: break; } } } base.RecordCommands(ref proxy); }
protected override void RecordCommandsInternal(ref MyRenderableProxy_2 proxy, int instanceIndex, int sectionIndex) { RC.SetSRVs(ref proxy.ObjectSRVs); RC.BindVertexData(ref proxy.VertexData); Debug.Assert(proxy.DepthShaders.MultiInstance.VS != null); RC.SetRS(DefaultRasterizer); RC.BindShaders(proxy.DepthShaders.MultiInstance); SetProxyConstants(ref proxy); for (int i = 0; i < proxy.SubmeshesDepthOnly.Length; i++) { var submesh = proxy.SubmeshesDepthOnly[i]; if (proxy.InstanceCount == 0) { switch (submesh.DrawCommand) { case MyDrawCommandEnum.DrawIndexed: RC.DeviceContext.DrawIndexed(submesh.Count, submesh.Start, submesh.BaseVertex); break; case MyDrawCommandEnum.Draw: RC.DeviceContext.Draw(submesh.Count, submesh.Start); break; default: break; } } else { switch (submesh.DrawCommand) { case MyDrawCommandEnum.DrawIndexed: //MyRender11.AddDebugQueueMessage("DepthPass DrawIndexedInstanced " + proxy.VertexData.VB[0].DebugName); RC.DeviceContext.DrawIndexedInstanced(submesh.Count, proxy.InstanceCount, submesh.Start, submesh.BaseVertex, proxy.StartInstance); break; case MyDrawCommandEnum.Draw: RC.DeviceContext.DrawInstanced(submesh.Count, proxy.InstanceCount, submesh.Start, proxy.StartInstance); break; default: break; } } } }
internal override void RecordCommands(ref MyRenderableProxy_2 proxy) { RC.SetSRVs(ref proxy.ObjectSRVs); RC.BindVertexData(ref proxy.VertexData); Debug.Assert(proxy.DepthShaders.VS != null); RC.SetRS(DefaultRasterizer); RC.BindShaders(proxy.DepthShaders); for (int i = 0; i < proxy.SubmeshesDepthOnly.Length; i++) { var submesh = proxy.SubmeshesDepthOnly[i]; //RC.SetSRVs(ref proxy.Submeshes[i].MaterialProxy.MaterialSRVs); if (proxy.InstanceCount == 0) { switch (submesh.DrawCommand) { case MyDrawCommandEnum.DrawIndexed: RC.Context.DrawIndexed(submesh.Count, submesh.Start, submesh.BaseVertex); break; case MyDrawCommandEnum.Draw: RC.Context.Draw(submesh.Count, submesh.Start); break; default: break; } } else { switch (submesh.DrawCommand) { case MyDrawCommandEnum.DrawIndexed: RC.Context.DrawIndexedInstanced(submesh.Count, proxy.InstanceCount, submesh.Start, submesh.BaseVertex, proxy.StartInstance); break; case MyDrawCommandEnum.Draw: RC.Context.DrawInstanced(submesh.Count, proxy.InstanceCount, submesh.Start, proxy.StartInstance); break; default: break; } } } base.RecordCommands(ref proxy); }
internal void UpdateProxySubmeshes(ref MyRenderableProxy_2 proxy, bool rootGroupDirtyTree) { if (m_mergeGroup.TableDirty) { proxy.Submeshes[0].Count = m_mergeGroup.VerticesNum; proxy.SubmeshesDepthOnly[0].Count = m_mergeGroup.VerticesNum; UpdateProxySectionSubmeshes(ref proxy); } else if (rootGroupDirtyTree) { UpdateProxySectionSubmeshes(ref proxy); } }
private void DrawSubmesh(ref MyRenderableProxy_2 proxy, ref MyDrawSubmesh_2 submesh, int instanceIndex) { var material = MyMaterials1.ProxyPool.Data[submesh.MaterialId.Index]; RC.MoveConstants(ref material.MaterialConstants); RC.SetConstants(ref material.MaterialConstants, MyCommon.MATERIAL_SLOT); RC.SetSRVs(ref material.MaterialSRVs); MyMergeInstancingConstants constants = new MyMergeInstancingConstants(); constants.InstanceIndex = instanceIndex; constants.StartIndex = submesh.Start; SetProxyConstants(ref proxy, constants); if (proxy.InstanceCount == 0) { switch (submesh.DrawCommand) { case MyDrawCommandEnum.DrawIndexed: RC.DeviceContext.DrawIndexed(submesh.Count, submesh.Start, submesh.BaseVertex); break; case MyDrawCommandEnum.Draw: RC.DeviceContext.Draw(submesh.Count, submesh.Start); break; default: break; } } else { switch (submesh.DrawCommand) { case MyDrawCommandEnum.DrawIndexed: RC.DeviceContext.DrawIndexedInstanced(submesh.Count, proxy.InstanceCount, submesh.Start, submesh.BaseVertex, proxy.StartInstance); break; case MyDrawCommandEnum.Draw: RC.DeviceContext.DrawInstanced(submesh.Count, proxy.InstanceCount, submesh.Start, proxy.StartInstance); break; default: break; } } Stats.Submeshes++; }
/// <returns>Actor full mesh indices count</returns> private void UpdateActorSubmeshes(ref MyRenderableProxy_2 proxy, MyActor actor, int actorIndex, int indexOffset) { MyRenderableComponent component = actor.GetRenderable(); MyRenderableProxy proxy1 = component.Lods[0].RenderableProxies[0]; MyDrawSubmesh_2 sectionSubmesh = proxy.Submeshes[0]; MyDrawSubmesh_2[] sectionSubmeshes = new MyDrawSubmesh_2[proxy1.SectionSubmeshes.Length]; proxy.SectionSubmeshes[actorIndex] = sectionSubmeshes; for (int it = 0; it < proxy1.SectionSubmeshes.Length; it++) { MyDrawSubmesh sectionSubmesh1 = proxy1.SectionSubmeshes[it]; sectionSubmesh.Count = sectionSubmesh1.IndexCount; sectionSubmesh.Start = indexOffset + sectionSubmesh1.StartIndex; sectionSubmeshes[it] = sectionSubmesh; } }
protected virtual void RecordCommandsInternal(ref MyRenderableProxy_2 proxy, int instance, int section) { }
protected override void RecordCommandsInternal(ref MyRenderableProxy_2 proxy, int instanceIndex, int sectionIndex) { MyRenderUtils.SetSrvs(RC, ref proxy.ObjectSrvs); Stats.Meshes++; if (instanceIndex == -1) { MyRenderUtils.BindShaderBundle(RC, proxy.HighlightShaders.MultiInstance); for (int it = 0; it < proxy.Submeshes.Length; it++) { MyDrawSubmesh_2 submesh = proxy.Submeshes[it]; DrawSubmesh(ref proxy, ref submesh, sectionIndex); } } else { MyRenderUtils.BindShaderBundle(RC, proxy.HighlightShaders.SingleInstance); MyDrawSubmesh_2 submesh; if (sectionIndex == -1) submesh = proxy.Submeshes[instanceIndex]; else submesh = proxy.SectionSubmeshes[instanceIndex][sectionIndex]; DrawSubmesh(ref proxy, ref submesh, instanceIndex); } }
internal void UpdateProxyVerticesNum(ref MyRenderableProxy_2 proxy) { proxy.Submeshes[0].Count = m_mergeGroup.VerticesNum; proxy.SubmeshesDepthOnly[0].Count = m_mergeGroup.VerticesNum; }
internal void RecordCommands(ref MyRenderableProxy_2 proxy, int instance = -1, int section = -1) { RecordCommandsInternal(ref proxy, instance, section); }
private void DrawSubmesh(ref MyRenderableProxy_2 proxy, ref MyDrawSubmesh_2 submesh, int instanceIndex) { var material = MyMaterials1.ProxyPool.Data[submesh.MaterialId.Index]; MyRenderUtils.MoveConstants(RC, ref material.MaterialConstants); MyRenderUtils.SetConstants(RC, ref material.MaterialConstants, MyCommon.MATERIAL_SLOT); MyRenderUtils.SetSrvs(RC, ref material.MaterialSrvs); MyMergeInstancingConstants constants = new MyMergeInstancingConstants(); constants.InstanceIndex = instanceIndex; constants.StartIndex = submesh.Start; SetProxyConstants(ref proxy, constants); if (proxy.InstanceCount == 0) { switch (submesh.DrawCommand) { case MyDrawCommandEnum.DrawIndexed: RC.DrawIndexed(submesh.Count, submesh.Start, submesh.BaseVertex); break; case MyDrawCommandEnum.Draw: RC.Draw(submesh.Count, submesh.Start); break; default: break; } } else { switch (submesh.DrawCommand) { case MyDrawCommandEnum.DrawIndexed: RC.DrawIndexedInstanced(submesh.Count, proxy.InstanceCount, submesh.Start, submesh.BaseVertex, proxy.StartInstance); break; case MyDrawCommandEnum.Draw: RC.DrawInstanced(submesh.Count, proxy.InstanceCount, submesh.Start, proxy.StartInstance); break; default: break; } } Stats.Submeshes++; }
internal virtual void RecordCommands(ref MyRenderableProxy_2 proxy) { }
internal override void RecordCommands(ref MyRenderableProxy_2 proxy) { }
protected override void RecordCommandsInternal(ref MyRenderableProxy_2 proxy, int instanceIndex, int sectionIndex) { throw new Exception(); }
protected unsafe void SetProxyConstants(ref MyRenderableProxy_2 proxy, MyMergeInstancingConstants? arg = null) { MyMergeInstancingConstants constants = arg ?? MyMergeInstancingConstants.Default; int version = constants.GetHashCode(); if (constants.GetHashCode() != proxy.ObjectConstants.Version) { int size = sizeof(MyMergeInstancingConstants); var buffer = new byte[sizeof(MyMergeInstancingConstants)]; proxy.ObjectConstants = new MyConstantsPack() { BindFlag = MyBindFlag.BIND_VS, CB = MyCommon.GetObjectCB(size), Version = version, Data = buffer }; fixed (byte* dstPtr = buffer) { MyMemory.CopyMemory(new IntPtr(dstPtr), new IntPtr(&constants), (uint)size); } } RC.MoveConstants(ref proxy.ObjectConstants); RC.SetConstants(ref proxy.ObjectConstants, MyCommon.OBJECT_SLOT); ++Stats.ObjectConstantsChanges; }
internal void RecordCommandLists(MyCullQuery processedCullQuery, Queue <CommandList> outCommandLists) { ProfilerShort.Begin("PrepareWork"); ProfilerShort.Begin("Init"); Debug.Assert(m_workList.Count == 0, "Work list not cleared after use!"); foreach (List <MyRenderCullResultFlat> cullResults in m_passElements) { cullResults.Clear(); m_resultListPool.Deallocate(cullResults); } m_passElements.Clear(); m_passElements2.Clear(); for (int renderPassIndex = 0; renderPassIndex < processedCullQuery.Size; ++renderPassIndex) { if (!MyRender11.DeferredContextsEnabled) { processedCullQuery.RenderingPasses[renderPassIndex].SetImmediate(true); } m_passElements.Add(m_resultListPool.Allocate()); m_passElements2.Add(null); } ProfilerShort.BeginNextBlock("Flatten"); for (int i = 0; i < processedCullQuery.Size; ++i) { m_affectedQueueIds.SetSize(0); var frustumQuery = processedCullQuery.FrustumCullQueries[i]; for (int renderPassIndex = 0; renderPassIndex < processedCullQuery.Size; renderPassIndex++) { if ((processedCullQuery.RenderingPasses[renderPassIndex].ProcessingMask & frustumQuery.Bitmask) > 0) { m_affectedQueueIds.Add(renderPassIndex); } } var cullProxies = frustumQuery.List; var queryType = frustumQuery.Type; foreach (MyCullProxy cullProxy in cullProxies) { var renderableProxies = cullProxy.RenderableProxies; if (renderableProxies == null) { continue; } for (int proxyIndex = 0; proxyIndex < renderableProxies.Length; ++proxyIndex) { var flag = renderableProxies[proxyIndex].DrawSubmesh.Flags; if (queryType == MyFrustumEnum.MainFrustum) { if ((flag & MyDrawSubmesh.MySubmeshFlags.Gbuffer) != MyDrawSubmesh.MySubmeshFlags.Gbuffer) { continue; } } else if (queryType == MyFrustumEnum.ShadowCascade || queryType == MyFrustumEnum.ShadowProjection) { if ((flag & MyDrawSubmesh.MySubmeshFlags.Depth) != MyDrawSubmesh.MySubmeshFlags.Depth) { continue; } } MyRenderableProxy renderableProxy = renderableProxies[proxyIndex]; ulong sortKey = cullProxy.SortingKeys[proxyIndex]; var item = new MyRenderCullResultFlat { SortKey = sortKey, RenderProxy = renderableProxy, }; if (renderableProxy.Material != MyMeshMaterialId.NULL && renderableProxy.Material.Info.Technique == MyMeshDrawTechnique.GLASS) { if (queryType == MyFrustumEnum.MainFrustum) { MyStaticGlassRenderer.Renderables.Add(item); } continue; } for (int queueIndex = 0; queueIndex < m_affectedQueueIds.Count; ++queueIndex) { var queueId = m_affectedQueueIds[queueIndex]; m_passElements[queueId].Add(item); } } } // proxy 2 var list2 = frustumQuery.List2; // flatten and sort m_flattenedKeys.SetSize(0); m_indirectionList.SetSize(0); m_location.SetSize(0); int indirectionCounter = 0; for (int list2Index = 0; list2Index < list2.Count; ++list2Index) { for (int sortKeyIndex = 0; sortKeyIndex < list2[list2Index].SortingKeys.Length; sortKeyIndex++) { m_flattenedKeys.Add(list2[list2Index].SortingKeys[sortKeyIndex]); m_indirectionList.Add(indirectionCounter++); m_location.Add(MyTuple.Create(list2Index, sortKeyIndex)); } } MyRenderableProxy_2[] flattenedProxies = null; if (indirectionCounter > 0) { flattenedProxies = new MyRenderableProxy_2[indirectionCounter]; } m_sortingKeysComparer.Values = m_flattenedKeys; m_indirectionList.Sort(0, m_indirectionList.Count, m_sortingKeysComparer); if (flattenedProxies != null) { for (int e = 0; e < indirectionCounter; e++) { var l = m_location[m_indirectionList[e]]; flattenedProxies[e] = list2[l.Item1].Proxies[l.Item2]; } } for (int l = 0; l < m_affectedQueueIds.Count; l++) { m_passElements2[m_affectedQueueIds[l]] = flattenedProxies; } } ProfilerShort.BeginNextBlock("Sort"); m_tmpSortListDictionary.Clear(); m_resultSortedKeys.Clear(); for (int i = 0; i < m_passElements.Count; i++) { var flatCullResults = m_passElements[i]; foreach (MyRenderCullResultFlat element in flatCullResults) { List <MyPassCullResult> sortList; if (!m_tmpSortListDictionary.TryGetValue(element.SortKey, out sortList)) { sortList = m_sortListPool.Allocate(); m_tmpSortListDictionary.Add(element.SortKey, sortList); m_resultSortedKeys.Add(element.SortKey); } sortList.Add(new MyPassCullResult() { PassIndex = i, CullResult = element }); } flatCullResults.Clear(); } m_resultSortedKeys.Sort(); foreach (ulong sortKey in m_resultSortedKeys) { List <MyPassCullResult> sortList = m_tmpSortListDictionary[sortKey]; foreach (var result in sortList) { m_passElements[result.PassIndex].Add(result.CullResult); } sortList.SetSize(0); m_sortListPool.Deallocate(sortList); } int jobsNum = GetRenderingThreadsNum(); // always amortize this path ProfilerShort.BeginNextBlock("WorkAmortization"); //passElements.RemoveAll(x => x.Count == 0); int workSum = 0; foreach (var list in m_passElements) { workSum += list.Count; } int batchWork = (workSum + jobsNum - 1) / jobsNum; Debug.Assert(m_subworks.Count == 0); int work = 0; for (int passElementIndex = 0; passElementIndex < m_passElements.Count; ++passElementIndex) { var flatCullResults = m_passElements[passElementIndex]; if (flatCullResults.Count == 0) { MyObjectPoolManager.Deallocate(processedCullQuery.RenderingPasses[passElementIndex]); processedCullQuery.RenderingPasses[passElementIndex] = null; if (m_passElements2[passElementIndex] == null || m_passElements2[passElementIndex].Length == 0) { continue; } } if (processedCullQuery.RenderingPasses[passElementIndex] == null) { continue; } int passBegin = 0; if (m_passElements2[passElementIndex] != null && m_passElements2[passElementIndex].Length > 0) { m_subworks.Add(new MyRenderingWorkItem { Pass = processedCullQuery.RenderingPasses[passElementIndex].Fork(), List2 = m_passElements2[passElementIndex] }); } while (passBegin < flatCullResults.Count) { int toTake = Math.Min(flatCullResults.Count - passBegin, batchWork - work); var workItem = new MyRenderingWorkItem { Renderables = flatCullResults, Begin = passBegin, End = passBegin + toTake }; if (toTake < flatCullResults.Count && workItem.End != workItem.Renderables.Count) { workItem.Pass = processedCullQuery.RenderingPasses[passElementIndex].Fork(); } else { workItem.Pass = processedCullQuery.RenderingPasses[passElementIndex]; processedCullQuery.RenderingPasses[passElementIndex] = null; // Consume the pass so it doesn't get cleaned up later with the cull query, but instead with the work item } m_subworks.Add(workItem); passBegin += toTake; work += toTake; Debug.Assert(work <= batchWork); if (work != batchWork) { continue; } if (MyRender11.DeferredContextsEnabled) { var renderWork = MyObjectPoolManager.Allocate <MyRenderingWorkRecordCommands>(); renderWork.Init(MyManagers.DeferredRCs.AcquireRC(), m_subworks); m_workList.Add(renderWork); } else { var renderWork = MyObjectPoolManager.Allocate <MyRenderingWorkRecordCommands>(); renderWork.Init(m_subworks); m_workList.Add(renderWork); } work = 0; m_subworks.Clear(); } } if (m_subworks.Count > 0) { if (MyRender11.DeferredContextsEnabled) { var renderWork = MyObjectPoolManager.Allocate <MyRenderingWorkRecordCommands>(); renderWork.Init(MyManagers.DeferredRCs.AcquireRC(), m_subworks); m_workList.Add(renderWork); } else { var renderWork = MyObjectPoolManager.Allocate <MyRenderingWorkRecordCommands>(); renderWork.Init(m_subworks); m_workList.Add(renderWork); } m_subworks.Clear(); } ProfilerShort.End(); ProfilerShort.End(); DoRecordingWork(outCommandLists); foreach (var renderWork in m_workList) { foreach (var pass in renderWork.Passes) { ProfilerShort.Begin(pass.DebugName); ProfilerShort.End(0, new VRage.Library.Utils.MyTimeSpan(pass.Elapsed)); } MyObjectPoolManager.Deallocate(renderWork); } m_workList.Clear(); }
internal static void Dispatch_LoopPassThenObject(List <MyRenderingPass> queues, MyCullQuery cullingResults, Queue <CommandList> accumulator) { MyRender11.GetRenderProfiler().StartProfilingBlock("PrepareWork"); m_workList.Clear(); accumulator.Clear(); List <List <MyRenderCullResultFlat> > passElements = new List <List <MyRenderCullResultFlat> >(); List <MyRenderableProxy_2[]> passElements2 = new List <MyRenderableProxy_2[]>(); foreach (var q in queues) { if (!MyRender11.DeferredContextsEnabled) { q.SetImmediate(true); } passElements.Add(new List <MyRenderCullResultFlat>()); passElements2.Add(null); } //bool okAfterCull = false; for (int i = 0; i < cullingResults.Size; i++) { var affectedQueueIds = new List <int>(); for (int j = 0; j < queues.Count; j++) { if ((queues[j].ProcessingMask & cullingResults.FrustumQuery[i].Bitmask) > 0) { affectedQueueIds.Add(j); } } //if (cullingResults.FrustumQuery[i].Type == MyFrustumEnum.MainFrustum) //{ // foreach (var e in cullingResults.FrustumQuery[i].List) // { // if (e.Proxies[0].Parent.m_owner.ID == 1417) // { // okAfterCull = true; // break; // } // } //} // proxy var list = cullingResults.FrustumQuery[i].List; for (int j = 0; j < list.Count; j++) { for (int k = 0; k < list[j].Proxies.Length; k++) { var proxy = list[j].Proxies[k]; var sortKey = list[j].SortingKeys[k]; for (int l = 0; l < affectedQueueIds.Count; l++) { var item = new MyRenderCullResultFlat(); item.renderProxy = proxy; item.sortKey = sortKey; passElements[affectedQueueIds[l]].Add(item); } } } // proxy 2 var list2 = cullingResults.FrustumQuery[i].List2; // flatten and sort List <UInt64> flattenedKeys = new List <ulong>(); List <int> indirection = new List <int>(); List <Tuple <int, int> > location = new List <Tuple <int, int> >(); int c = 0; for (int a = 0; a < list2.Count; a++) { for (int b = 0; b < list2[a].SortingKeys.Length; b++) { flattenedKeys.Add(list2[a].SortingKeys[b]); indirection.Add(c++); location.Add(Tuple.Create(a, b)); } } MyRenderableProxy_2[] flattenedProxies = new MyRenderableProxy_2[c]; var comparerer = new MySortingKeysComparerer(); comparerer.Values = flattenedKeys; indirection.Sort(0, indirection.Count, comparerer); for (int e = 0; e < c; e++) { var l = location[indirection[e]]; flattenedProxies[e] = list2[l.Item1].Proxies[l.Item2]; } for (int l = 0; l < affectedQueueIds.Count; l++) { passElements2[affectedQueueIds[l]] = flattenedProxies; } } foreach (var list in passElements) { list.Sort(MyCullResultsComparer.Instance); } //var okAfterSort = false; //for (int i = 0; i < queues.Count; i++ ) //{ // if (queues[i] as MyGBufferPass != null) // { // foreach (var e in passElements[i]) // { // if (e.renderProxy.Parent.m_owner.ID == 1417) // { // okAfterSort = true; // break; // } // } // } //} int jobsNum = GetRenderingThreadsNum(); // always amortize this path MyRender11.GetRenderProfiler().StartProfilingBlock("WorkAmortization"); //passElements.RemoveAll(x => x.Count == 0); int workSum = 0; foreach (var list in passElements) { workSum += list.Count; } int batchWork = (workSum + jobsNum - 1) / jobsNum; //var renderingWork = new MyRenderingWork_LoopPassObject(); var subworks = new List <MyRenderingWorkItem>(); int work = 0; for (int i = 0; i < passElements.Count; i++) { var list = passElements[i]; int passBegin = 0; subworks.Add(new MyRenderingWorkItem { Pass = queues[i].Fork(), List2 = passElements2[i] }); while (passBegin < list.Count) { var toTake = Math.Min(list.Count - passBegin, batchWork - work); var workItem = new MyRenderingWorkItem(); if (toTake < list.Count) { workItem.Pass = queues[i].Fork(); } else { workItem.Pass = queues[i]; } workItem.Renderables = list; workItem.Begin = passBegin; workItem.End = passBegin + toTake; //renderingWork.m_subworks.Add(workItem); subworks.Add(workItem); passBegin += toTake; work += toTake; if (work == batchWork) { if (MyRender11.DeferredContextsEnabled) { m_workList.Add(new MyRenderingWork_LoopPassThenObject(MyRenderContextPool.AcquireRC(), subworks)); } else { m_workList.Add(new MyRenderingWork_LoopPassThenObject(subworks)); } work = 0; subworks = new List <MyRenderingWorkItem>(); ///renderingWork = new MyRenderingWork_LoopPassObject(, subworks); } } } if (subworks.Count > 0) { if (MyRender11.DeferredContextsEnabled) { m_workList.Add(new MyRenderingWork_LoopPassThenObject(MyRenderContextPool.AcquireRC(), subworks)); } else { m_workList.Add(new MyRenderingWork_LoopPassThenObject(subworks)); } } //bool okInWorklist = false; //foreach(var wl in m_workList) //{ // var impl = wl as MyRenderingWork_LoopPassThenObject; // foreach(var sub in impl.m_subworks) // { // if((sub.Pass as MyGBufferPass) != null && sub.Renderables != null) // { // foreach(var r in sub.Renderables) // { // if(r.renderProxy.Parent.m_owner.ID == 1417) // { // okInWorklist = true; // break; // } // } // } // } //} MyRender11.GetRenderProfiler().EndProfilingBlock(); MyRender11.GetRenderProfiler().EndProfilingBlock(); ScheduleAndWait(accumulator); }
protected override void RecordCommandsInternal(ref MyRenderableProxy_2 proxy, int instanceIndex, int sectionIndex) { MyRenderUtils.SetSrvs(RC, ref proxy.ObjectSrvs); Debug.Assert(proxy.Shaders.MultiInstance.VS != null); MyRenderUtils.BindShaderBundle(RC, proxy.Shaders.MultiInstance); SetDepthStencilView(false); SetProxyConstants(ref proxy); for (int i = 0; i < proxy.Submeshes.Length; i++) { var submesh = proxy.Submeshes[i]; var material = MyMaterials1.ProxyPool.Data[submesh.MaterialId.Index]; MyRenderUtils.MoveConstants(RC, ref material.MaterialConstants); MyRenderUtils.SetConstants(RC, ref material.MaterialConstants, MyCommon.MATERIAL_SLOT); MyRenderUtils.SetSrvs(RC, ref material.MaterialSrvs); if (proxy.InstanceCount == 0) { switch (submesh.DrawCommand) { case MyDrawCommandEnum.DrawIndexed: if (!MyStereoRender.Enable) { RC.DrawIndexed(submesh.Count, submesh.Start, submesh.BaseVertex); } else { MyStereoRender.DrawIndexedGBufferPass(RC, submesh.Count, submesh.Start, submesh.BaseVertex); } break; case MyDrawCommandEnum.Draw: if (!MyStereoRender.Enable) { RC.Draw(submesh.Count, submesh.Start); } else { MyStereoRender.DrawGBufferPass(RC, submesh.Count, submesh.Start); } break; default: break; } } else { switch (submesh.DrawCommand) { case MyDrawCommandEnum.DrawIndexed: if (!MyStereoRender.Enable) { RC.DrawIndexedInstanced(submesh.Count, proxy.InstanceCount, submesh.Start, submesh.BaseVertex, proxy.StartInstance); } else { MyStereoRender.DrawIndexedInstancedGBufferPass(RC, submesh.Count, proxy.InstanceCount, submesh.Start, submesh.BaseVertex, proxy.StartInstance); } break; case MyDrawCommandEnum.Draw: if (!MyStereoRender.Enable) { RC.DrawInstanced(submesh.Count, proxy.InstanceCount, submesh.Start, proxy.StartInstance); } else { MyStereoRender.DrawInstancedGBufferPass(RC, submesh.Count, proxy.InstanceCount, submesh.Start, proxy.StartInstance); } break; default: break; } } } }
protected override void RecordCommandsInternal(ref MyRenderableProxy_2 proxy, int instanceIndex, int sectionIndex) { MyRenderUtils.SetSrvs(RC, ref proxy.ObjectSrvs); Debug.Assert(proxy.Shaders.MultiInstance.VS != null); MyRenderUtils.BindShaderBundle(RC, proxy.Shaders.MultiInstance); SetDepthStencilView(false); SetProxyConstants(ref proxy); for (int i = 0; i < proxy.Submeshes.Length; i++) { var submesh = proxy.Submeshes[i]; var material = MyMaterials1.ProxyPool.Data[submesh.MaterialId.Index]; MyRenderUtils.MoveConstants(RC, ref material.MaterialConstants); MyRenderUtils.SetConstants(RC, ref material.MaterialConstants, MyCommon.MATERIAL_SLOT); MyRenderUtils.SetSrvs(RC, ref material.MaterialSrvs); if (proxy.InstanceCount == 0) { switch (submesh.DrawCommand) { case MyDrawCommandEnum.DrawIndexed: if (!MyStereoRender.Enable) RC.DrawIndexed(submesh.Count, submesh.Start, submesh.BaseVertex); else MyStereoRender.DrawIndexedGBufferPass(RC, submesh.Count, submesh.Start, submesh.BaseVertex); break; case MyDrawCommandEnum.Draw: if (!MyStereoRender.Enable) RC.Draw(submesh.Count, submesh.Start); else MyStereoRender.DrawGBufferPass(RC, submesh.Count, submesh.Start); break; default: break; } } else { switch (submesh.DrawCommand) { case MyDrawCommandEnum.DrawIndexed: if (!MyStereoRender.Enable) RC.DrawIndexedInstanced(submesh.Count, proxy.InstanceCount, submesh.Start, submesh.BaseVertex, proxy.StartInstance); else MyStereoRender.DrawIndexedInstancedGBufferPass(RC, submesh.Count, proxy.InstanceCount, submesh.Start, submesh.BaseVertex, proxy.StartInstance); break; case MyDrawCommandEnum.Draw: if (!MyStereoRender.Enable) RC.DrawInstanced(submesh.Count, proxy.InstanceCount, submesh.Start, proxy.StartInstance); else MyStereoRender.DrawInstancedGBufferPass(RC, submesh.Count, proxy.InstanceCount, submesh.Start, proxy.StartInstance); break; default: break; } } } }