public void Render(DX11RenderContext context, DX11RenderSettings settings) { Device device = context.Device; DeviceContext ctx = context.CurrentDeviceContext; bool popstate = false; bool multistate = this.FInState.IsConnected && this.FInState.SliceCount > 1; bool stateConnected = this.FInState.IsConnected; if (this.FInEnabled[0]) { //In that case we do not care about geometry, but only apply pass for globals if (settings.RenderHint == eRenderHint.ApplyOnly) { this.ApplyOnly(context, settings); return; } if (settings.RenderHint == eRenderHint.Collector) { this.Collect(context, settings); return; } DX11ShaderData shaderdata = this.deviceshaderdata[context]; if ((shaderdata.IsValid && (this.geomconnected || settings.Geometry != null) && this.spmax > 0 && this.varmanager.SetGlobalSettings(shaderdata.ShaderInstance, settings)) || this.FInApplyOnly[0]) { this.OnBeginQuery(context); //Select preferred technique if available if (settings.PreferredTechniques.Count == 0 && this.techniqueindex != this.FInTechnique[0].Index) { this.techniqueindex = this.FInTechnique[0].Index; this.techniquechanged = true; } else if (settings.PreferredTechniques.Count > 0) { int i = settings.GetPreferredTechnique(this.FShader); if (i == -1) { i = this.FInTechnique[0].Index; } if (i != this.techniqueindex) { this.techniqueindex = i; this.techniquechanged = true; } } //Need to build input layout if (this.FGeometry.IsChanged || this.techniquechanged || shaderdata.LayoutValid.Count == 0) { shaderdata.Update(this.techniqueindex, 0, this.FGeometry); this.FOutLayoutValid.AssignFrom(shaderdata.LayoutValid); this.FOutLayoutMsg.AssignFrom(shaderdata.LayoutMsg); int errorCount = 0; StringBuilder sbMsg = new StringBuilder(); sbMsg.Append("Invalid layout detected for slices:"); for (int i = 0; i < shaderdata.LayoutValid.Count; i++) { if (shaderdata.LayoutValid[i] == false) { errorCount++; sbMsg.Append(i + ","); } } if (errorCount > 0) { this.FHost.Log(TLogType.Warning, sbMsg.ToString()); } this.techniquechanged = false; } if (this.stateconnected && !multistate) { context.RenderStateStack.Push(this.FInState[0]); popstate = true; } ShaderPipelineState pipelineState = null; if (!settings.PreserveShaderStages) { shaderdata.ResetShaderStages(ctx); } else { pipelineState = new ShaderPipelineState(context); } settings.DrawCallCount = spmax; //Set number of draw calls var objectsettings = this.objectSettings[context]; #pragma warning disable 0618 objectsettings.GeometryFromLayer = false; #pragma warning restore 0618 var orderedobjectsettings = this.orderedObjectSettings[context]; var variableCache = this.shaderVariableCache[context]; variableCache.ApplyGlobals(settings); //IDX11Geometry drawgeom = null; objectsettings.Geometry = null; DX11Resource <IDX11Geometry> pg = null; bool doOrder = false; List <int> orderedSlices = null; if (settings.LayerOrder != null && settings.LayerOrder.Enabled) { orderedobjectsettings.Clear(); for (int i = 0; i < this.spmax; i++) { DX11ObjectRenderSettings objSettings = new DX11ObjectRenderSettings(); objSettings.DrawCallIndex = i; objSettings.Geometry = null; objSettings.IterationCount = 1; objSettings.IterationIndex = 0; objSettings.WorldTransform = this.mworld[i % this.mworldcount]; objSettings.RenderStateTag = stateConnected ? this.FInState[i].Tag : null; orderedobjectsettings.Add(objSettings); } orderedSlices = settings.LayerOrder.Reorder(settings, orderedobjectsettings); doOrder = true; } int drawCount = doOrder ? orderedSlices.Count : this.spmax; if (this.spmax == 0) { drawCount = 0; } bool singleGeometry = this.FGeometry.SliceCount == 1 || settings.Geometry != null; if (settings.Geometry != null && this.FGeometry.IsConnected == false) { #pragma warning disable 0618 objectsettings.GeometryFromLayer = true; #pragma warning restore 0618 objectsettings.Geometry = settings.Geometry; singleGeometry = true; if (!shaderdata.SetInputAssemblerFromLayer(ctx, objectsettings.Geometry, 0)) { return; } } else if (singleGeometry) { pg = this.FGeometry[0]; objectsettings.Geometry = pg[context]; if (objectsettings.Geometry == null) { objectsettings.Geometry = new DX11InvalidGeometry(); } shaderdata.SetInputAssembler(ctx, objectsettings.Geometry, 0); } if (!multistate) { objectsettings.RenderStateTag = this.FInState[0] != null ? this.FInState[0].Tag : null; } for (int i = 0; i < drawCount; i++) { int idx = doOrder ? orderedSlices[i] : i; if (multistate) { context.RenderStateStack.Push(this.FInState[idx]); objectsettings.RenderStateTag = this.FInState[idx] != null ? this.FInState[idx].Tag : null; } if (shaderdata.IsLayoutValid(idx) || settings.Geometry != null) { objectsettings.IterationCount = this.FIter[idx]; for (int k = 0; k < objectsettings.IterationCount; k++) { objectsettings.IterationIndex = k; if (!singleGeometry) { if (settings.Geometry == null) { if (this.FGeometry[idx] != pg) { pg = this.FGeometry[idx]; objectsettings.Geometry = pg[context]; if (objectsettings.Geometry == null) { objectsettings.Geometry = new DX11InvalidGeometry(); } shaderdata.SetInputAssembler(ctx, objectsettings.Geometry, idx); } } else { objectsettings.Geometry = settings.Geometry; shaderdata.SetInputAssembler(ctx, objectsettings.Geometry, idx); } } //Prepare settings objectsettings.DrawCallIndex = idx; objectsettings.WorldTransform = this.mworld[idx % this.mworldcount]; if (settings.ValidateObject(objectsettings)) { variableCache.ApplySlice(objectsettings, idx); for (int ip = 0; ip < shaderdata.PassCount; ip++) { shaderdata.ApplyPass(ctx, ip); if (settings.DepthOnly) { ctx.PixelShader.Set(null); } objectsettings.Geometry.Draw(); } } } } if (multistate) { context.RenderStateStack.Pop(); } } shaderdata.ShaderInstance.CleanUp(); if (pipelineState != null) { pipelineState.Restore(context); } this.OnEndQuery(context); } //this.query.End(); } if (popstate) { context.RenderStateStack.Pop(); } else { //Since shaders can define their own states, reapply top of the stack context.RenderStateStack.Apply(); } if (this.FInLayer.IsConnected && this.FInEnabled[0]) { this.FInLayer.RenderAll(context, settings); } }