protected internal override void Execute(ParallelizationProvider pp) { // See if we need to resize the light plane and get the new GBuffer Camera input; SceneViewport output; Texture2D <TexelFormat.RGBA32Float>[] currentGBuffer; geometryPass.GetLightPassParameters(out currentGBuffer, out input, out output); Vector2 outputSizePixels = output.SizePixels; if (outputSizePixels.X <= 0f || outputSizePixels.Y <= 0f) { return; } RenderTargetViewHandle windowRTV; DepthStencilViewHandle windowDSV; bool windowStillOpen = output.TargetWindow.GetWindowRTVAndDSV(out windowRTV, out windowDSV); if (!windowStillOpen) { return; } CheckGeometryPassParameters(currentGBuffer, outputSizePixels); // Clear the bloom textures QueueRenderCommand(RenderCommand.ClearRenderTarget(preBloomBufferRTV)); QueueRenderCommand(RenderCommand.ClearRenderTarget(reducedBloomBufferRTV)); QueueRenderCommand(RenderCommand.ClearRenderTarget(bloomTargetBufferRTV)); QueueRenderCommand(RenderCommand.ClearRenderTarget(nonDepthOfFieldBackBufferRTV)); QueueRenderCommand(RenderCommand.ClearRenderTarget(reducedNonDepthOfFieldBackBufferRTV)); QueueRenderCommand(RenderCommand.ClearRenderTarget(depthOfFieldBackBufferRTV)); QueueRenderCommand(RenderCommand.ClearDepthStencil(bloomResizeCopyDSDSV)); QueueRenderCommand(RenderCommand.ClearDepthStencil(dsThrowawayBufferDSV)); // Set topology QueueRenderCommand(RenderCommand.SetPrimitiveTopology(RenderCommand.DEFAULT_PRIMITIVE_TOPOLOGY)); // Set input layout QueueRenderCommand(RenderCommand.SetInputLayout(lightPlaneInputLayout)); // Enqueue VS commands QueueShaderSwitch(dlLightVS); QueueShaderResourceUpdate(dlLightVS, vsResPackage); /* ======================================= * STAGE: DYNAMIC LIGHTING APPLICATION * ======================================= */ // Enqueue FS commands Vector4 cameraPos = input.Position; ((ConstantBufferBinding)dlLightFS.GetBindingByIdentifier("CameraProperties")).SetValue((byte *)(&cameraPos)); QueueShaderSwitch(dlLightFS); // Set rasterizer state QueueRenderCommand(RenderCommand.SetRasterizerState(rsState)); QueueRenderCommand(RenderCommand.SetViewport(output)); // Set depth stencil state QueueRenderCommand(RenderCommand.SetDepthStencilState(dsState)); // Set blend state QueueRenderCommand(RenderCommand.SetBlendState(blendState)); // Set up output merger QueueRenderCommand(RenderCommand.SetRenderTargets(dsThrowawayBufferDSV.ResourceViewHandle, nonDepthOfFieldBackBufferRTV.ResourceViewHandle, preBloomBufferRTV.ResourceViewHandle)); // Draw lights //input = new Camera(); //input.Position = Vector3.ZERO; //input.Orient(Vector3.FORWARD, Vector3.UP); var frustum = input.GetFrustum(output); int numLights = addedLights.Count; int numLightsInFrustum = 0; for (int i = 0; i < numLights; ++i) { if (!frustum.IsWithinFrustum(new Sphere(addedLights[i].Position, addedLights[i].Radius))) { continue; } lightPropsWorkspace[numLightsInFrustum++] = addedLights[i].Properties; } if (numLightsInFrustum > dynamicLightCap) { dynamicLightComparer.CameraPosition = input.Position; Array.Sort(lightPropsWorkspace, 0, numLightsInFrustum, dynamicLightComparer); numLightsInFrustum = dynamicLightCap; } Buffer <LightProperties> lightBuffer = (Buffer <LightProperties>)(((ResourceViewBinding)dlLightFS.GetBindingByIdentifier("LightBuffer")).GetBoundResource().Resource); var lightMetaCBuffer = (ConstantBufferBinding)dlLightFS.GetBindingByIdentifier("LightMeta"); QueueShaderResourceUpdate(dlLightFS, fsResPackage); Array.Clear(perTileLightPropCounts, 0, perTileLightPropCounts.Length); Vector3 upDir = input.UpDirection; Vector3 downDir = -input.UpDirection; Vector3 rightDir = upDir.Cross(input.Orientation); Vector3 leftDir = -rightDir; var worldToProjMat = (*((Matrix *)input.GetRecalculatedViewMatrix()) * *((Matrix *)output.GetRecalculatedProjectionMatrix(input))); for (int i = 0; i < numLightsInFrustum; ++i) { var lightProps = lightPropsWorkspace[i]; //lightProps = new LightProperties( // Vector3.LEFT + Vector3.BACKWARD, 3f, Vector3.ONE //); var lightCentre = lightProps.Position; var lightTop = new Vector4(lightCentre + upDir * lightProps.Radius, w: 1f); var lightBottom = new Vector4(lightCentre + downDir * lightProps.Radius, w: 1f); var lightLeftmost = new Vector4(lightCentre + leftDir * lightProps.Radius, w: 1f); var lightRightmost = new Vector4(lightCentre + rightDir * lightProps.Radius, w: 1f); var lightTopProjspace = lightTop * worldToProjMat; var lightBottomProjspace = lightBottom * worldToProjMat; var lightLeftmostProjspace = lightLeftmost * worldToProjMat; var lightRightmostProjspace = lightRightmost * worldToProjMat; var lightTopScreenSpace = lightTopProjspace / Math.Abs(lightTopProjspace.W); var lightBottomScreenSpace = lightBottomProjspace / Math.Abs(lightBottomProjspace.W); var lightLeftmostScreenSpace = lightLeftmostProjspace / Math.Abs(lightLeftmostProjspace.W); var lightRightmostScreenSpace = lightRightmostProjspace / Math.Abs(lightRightmostProjspace.W); var xMin = ((float)MathUtils.Clamp(lightLeftmostScreenSpace.X, -1f, 1f) + 1f) * 0.5f; var xMax = ((float)MathUtils.Clamp(lightRightmostScreenSpace.X, -1f, 1f) + 1f) * 0.5f; var yMin = ((float)MathUtils.Clamp(lightBottomScreenSpace.Y, -1f, 1f) + 1f) * 0.5f; var yMax = ((float)MathUtils.Clamp(lightTopScreenSpace.Y, -1f, 1f) + 1f) * 0.5f; for (int x = 0; x < LIGHTING_TILE_GRANULARITY; ++x) { for (int y = 0; y < LIGHTING_TILE_GRANULARITY; ++y) { var tileXMin = tileOffsetsX[x]; var tileXMax = tileOffsetsX[x + 1]; var tileYMin = tileOffsetsY[y]; var tileYMax = tileOffsetsY[y + 1]; if (xMax < tileXMin || xMin > tileXMax || yMax < tileYMin || yMin > tileYMax) { continue; } var bucketIndex = x * LIGHTING_TILE_GRANULARITY + y; perTileLightPropsWorkspace[bucketIndex][perTileLightPropCounts[bucketIndex]++] = lightProps; } } } for (int x = 0; x < LIGHTING_TILE_GRANULARITY; ++x) { for (int y = 0; y < LIGHTING_TILE_GRANULARITY; ++y) { var bucketIndex = x * LIGHTING_TILE_GRANULARITY + y; var numLightsOnThisTile = perTileLightPropCounts[bucketIndex]; if (numLightsOnThisTile == 0) { continue; } var scalars = new Vector4(tileOffsetsX[x], tileOffsetsX[x + 1], tileOffsetsY[y], tileOffsetsY[y + 1]); // 0f to 1f, from bottom left corner QueueRenderCommand(RenderCommand.DiscardWriteShaderConstantBuffer( lightBuffer, new ArraySlice <LightProperties>(perTileLightPropsWorkspace[bucketIndex], 0U, (uint)numLightsOnThisTile), (uint)sizeof(LightProperties) )); int *numLightsWithPadding = stackalloc int[4]; numLightsWithPadding[0] = numLightsOnThisTile; QueueRenderCommand(RenderCommand.DiscardWriteShaderConstantBuffer(lightMetaCBuffer, (IntPtr)(numLightsWithPadding))); QueueRenderCommand(RenderCommand.DiscardWriteShaderConstantBuffer(lightVSScalarsBufferBinding, (IntPtr)(&scalars))); QueueRenderCommand(RenderCommand.Draw(0, 3U)); QueueRenderCommand(RenderCommand.Draw(3, 3U)); } } // Unbind gbuffer QueueShaderResourceUpdate(dlLightFS, fsUnbindResPackage); /* ======================================= * STAGE: ADD AMBIENT LIGHT (DL FINAL) * ======================================= */ // Switch to finalization shader var scalarsFinal = new Vector4(0f, 1f, 0f, 1f); QueueRenderCommand(RenderCommand.DiscardWriteShaderConstantBuffer(lightVSScalarsBufferBinding, (IntPtr)(&scalarsFinal))); QueueShaderSwitch(dlFinalFS); QueueShaderResourceUpdate(dlFinalFS, finalizationShaderResPackage); // Draw finalization triangles QueueRenderCommand(RenderCommand.Draw(0, 3U)); QueueRenderCommand(RenderCommand.Draw(3, 3U)); // Unbind resources QueueShaderResourceUpdate(dlFinalFS, finalizationShaderUnbindResPackage); /* ======================================= * STAGE: OUTLINING * ======================================= */ // Switch to outlining shader QueueShaderSwitch(outliningShader); QueueShaderResourceUpdate(outliningShader, outliningShaderResPackage); // Set blend state QueueRenderCommand(RenderCommand.SetBlendState(outliningBlendState)); // Draw outlining triangles QueueRenderCommand(RenderCommand.Draw(0, 3U)); QueueRenderCommand(RenderCommand.Draw(3, 3U)); // Unbind resources QueueShaderResourceUpdate(outliningShader, outliningShaderUnbindResPackage); /* ======================================= * STAGE: DOWNSCALE PRE-BLOOM BUFFER TEX * ======================================= */ // Set up output merger QueueRenderCommand(RenderCommand.SetRenderTargets(bloomResizeCopyDSDSV, reducedBloomBufferRTV)); // Switch to copy shader QueueShaderSwitch(copyShader); QueueShaderResourceUpdate(copyShader, copyShaderResPackage); // Set blend state QueueRenderCommand(RenderCommand.SetBlendState(blendState)); // Draw fullscreen triangles QueueRenderCommand(RenderCommand.Draw(0, 3U)); QueueRenderCommand(RenderCommand.Draw(3, 3U)); // Unbind resources QueueShaderResourceUpdate(copyShader, copyShaderUnbindResPackage); /* ======================================= * STAGE: BLOOM RENDER TO BLOOM TARGET * ======================================= */ // Clear DSV QueueRenderCommand(RenderCommand.ClearDepthStencil(bloomResizeCopyDSDSV)); // Set up output merger QueueRenderCommand(RenderCommand.SetRenderTargets(bloomResizeCopyDSDSV, bloomTargetBufferRTV)); // Switch to bloom H shader QueueShaderSwitch(bloomHShader); QueueShaderResourceUpdate(bloomHShader, bloomHShaderResPackage); // Draw fullscreen triangles QueueRenderCommand(RenderCommand.Draw(0, 3U)); QueueRenderCommand(RenderCommand.Draw(3, 3U)); // Unbind resources QueueShaderResourceUpdate(bloomHShader, bloomHShaderUnbindResPackage); // Switch to bloom V shader QueueShaderSwitch(bloomVShader); QueueShaderResourceUpdate(bloomVShader, bloomVShaderResPackage); // Draw fullscreen triangles QueueRenderCommand(RenderCommand.Draw(0, 3U)); QueueRenderCommand(RenderCommand.Draw(3, 3U)); // Unbind resources QueueShaderResourceUpdate(bloomVShader, bloomVShaderUnbindResPackage); /* ======================================= * STAGE: COPY BLOOM RESULT ON TO NON-DoF BUFFER * ======================================= */ // Set up output merger QueueRenderCommand(RenderCommand.SetRenderTargets(dsThrowawayBufferDSV.ResourceViewHandle, nonDepthOfFieldBackBufferRTV)); // Switch to reverse copy shader QueueShaderSwitch(copyReverseShader); QueueShaderResourceUpdate(copyReverseShader, copyReverseShaderResPackage); // Draw fullscreen triangles QueueRenderCommand(RenderCommand.Draw(0, 3U)); QueueRenderCommand(RenderCommand.Draw(3, 3U)); // Unbind resources QueueShaderResourceUpdate(copyReverseShader, copyReverseShaderUnbindResPackage); /* ======================================= * STAGE: DOWNSCALE NON-DoF SCENE * ======================================= */ // Set up output merger QueueRenderCommand(RenderCommand.SetRenderTargets(bloomResizeCopyDSDSV, reducedNonDepthOfFieldBackBufferRTV)); // Switch to copy shader QueueShaderSwitch(copyShader); QueueShaderResourceUpdate(copyShader, copyDoFShaderResPackage); // Set blend state QueueRenderCommand(RenderCommand.SetBlendState(blendState)); // Draw fullscreen triangles QueueRenderCommand(RenderCommand.Draw(0, 3U)); QueueRenderCommand(RenderCommand.Draw(3, 3U)); // Unbind resources QueueShaderResourceUpdate(copyShader, copyDoFShaderUnbindResPackage); /* ======================================= * STAGE: BLUR NON-DoF SCENE * ======================================= */ // Set up output merger QueueRenderCommand(RenderCommand.SetRenderTargets(bloomResizeCopyDSDSV, depthOfFieldBackBufferRTV)); // Switch to copy shader QueueShaderSwitch(blurShader); QueueShaderResourceUpdate(blurShader, blurShaderResPackage); // Set blend state QueueRenderCommand(RenderCommand.SetBlendState(blendState)); // Draw fullscreen triangles QueueRenderCommand(RenderCommand.Draw(0, 3U)); QueueRenderCommand(RenderCommand.Draw(3, 3U)); // Unbind resources QueueShaderResourceUpdate(blurShader, blurShaderUnbindResPackage); /* ======================================= * STAGE: RENDER TO BACK BUFFER WITH DoF SELECTION * ======================================= */ // Set up output merger QueueRenderCommand(RenderCommand.SetRenderTargets(windowDSV, windowRTV)); // Switch to copy shader QueueShaderSwitch(dofShader); QueueShaderResourceUpdate(dofShader, dofShaderResPackage); // Set blend state QueueRenderCommand(RenderCommand.SetBlendState(blendState)); // Draw fullscreen triangles QueueRenderCommand(RenderCommand.Draw(0, 3U)); QueueRenderCommand(RenderCommand.Draw(3, 3U)); // Unbind resources QueueShaderResourceUpdate(dofShader, dofShaderUnbindResPackage); // Flush + present FlushRenderCommands(); if (presentAfterPass) { PresentBackBuffer(output.TargetWindow); } }
protected internal override void Execute(ParallelizationProvider pp) { for (int i = 0; i < NUM_GBUFFER_TEXTURES; ++i) { if (gBufferViews[i] != null) { QueueRenderCommand(RenderCommand.ClearRenderTarget(gBufferViews[i])); } } if (clearOutputBeforePass) { QueueRenderCommand(RenderCommand.ClearRenderTarget(output.TargetWindow)); QueueRenderCommand(RenderCommand.ClearDepthStencil(output.TargetWindow)); } Vector2 outputSizePixels = output.SizePixels; if (gBuffer[0] == null || gBuffer[0].Width != (uint)outputSizePixels.X || gBuffer[0].Height != (uint)outputSizePixels.Y) { for (int i = 0; i < NUM_GBUFFER_TEXTURES; ++i) { if (gBufferViews[i] != null) { gBufferViews[i].Dispose(); } if (gBuffer[i] != null) { gBuffer[i].Dispose(); } gBuffer[i] = gBufferBuilder.WithWidth((uint)outputSizePixels.X).WithHeight((uint)outputSizePixels.Y); gBufferViews[i] = gBuffer[i].CreateRenderTargetView(0U); } } if (primaryDSBuffer == null || primaryDSBuffer.Width != outputSizePixels.X || primaryDSBuffer.Height != outputSizePixels.Y) { if (primaryDSBuffer != null) { primaryDSBuffer.Dispose(); } if (primaryDSBufferDSV != null) { primaryDSBufferDSV.Dispose(); } if (primaryDSBufferSRV != null) { primaryDSBufferSRV.Dispose(); } primaryDSBuffer = dsBufferBuilder.WithWidth((uint)outputSizePixels.X).WithHeight((uint)outputSizePixels.Y); primaryDSBufferDSV = primaryDSBuffer.CreateDepthStencilView <TexelFormat.DepthStencil>(0U); primaryDSBufferSRV = primaryDSBuffer.CreateView <TexelFormat.R24UnormX8Typeless>(0U, 1U); } previousShadowBufferSRV = shadowPass.ShadowBufferSRV; // Clear main DSV QueueRenderCommand(RenderCommand.ClearDepthStencil(primaryDSBufferDSV)); List <GeometryCache> activeCaches = GeometryCache.ActiveCaches; foreach (GeometryCache c in activeCaches) { if (!deferredGeometryVertexShaders.ContainsKey(c)) { continue; } currentVS = deferredGeometryVertexShaders[c]; // Set view/proj matrices var vpMatrices = new GeomPassProjViewMatrices { MainCameraVPMat = (*((Matrix *)Input.GetRecalculatedViewMatrix()) * *((Matrix *)Output.GetRecalculatedProjectionMatrix(Input))).Transpose, ShadowCameraVPMat = (*((Matrix *)shadowPass.LightCam.GetRecalculatedViewMatrix()) * *((Matrix *)Output.GetRecalculatedProjectionMatrix(shadowPass.LightCam))).Transpose }; byte *vpMatPtr = (byte *)&vpMatrices; currentVS.ViewProjMatBinding.SetValue(vpMatPtr); // Set state for current cache cpuInstanceBufferCurIndex = 0; List <SceneLayer> allEnabledLayers = Scene.EnabledLayers; uint maxLayer = 0U; for (int i = 0; i < allEnabledLayers.Count; ++i) { if (allEnabledLayers[i].Index > maxLayer) { maxLayer = allEnabledLayers[i].Index; } } if (allEnabledLayers.Count > 0 && currentSceneLayers.Length <= maxLayer) { currentSceneLayers = new SceneLayer[maxLayer + 1U]; } Array.Clear(currentSceneLayers, 0, currentSceneLayers.Length); foreach (SceneLayer layer in allEnabledLayers) { currentSceneLayers[layer.Index] = layer; } currentCache = c; ++frameNum; Thread.MemoryBarrier(); currentInstanceData = currentCache.GetModelInstanceData(); // Set up each thread pp.InvokeOnAll(setUpCacheForLocalThreadAct, true); // membar here // Iterate all model instances (ordered by material) pp.Execute((int)currentInstanceData.Length, (int)(currentInstanceData.Length / (pp.NumThreads << 3)) + 1, renderCacheIterateMatAct); // Set instance buffer and write to it if (gpuInstanceBuffer == null || gpuInstanceBuffer.Length < cpuInstanceBuffer.Length) { if (gpuInstanceBuffer != null) { gpuInstanceBuffer.Dispose(); } gpuInstanceBuffer = gpuInstanceBufferBuilder.WithLength((uint)cpuInstanceBuffer.Length).Create(); } gpuInstanceBuffer.DiscardWrite(cpuInstanceBuffer); // Happens immediately (required) // Unbind shadow buffer QueueShaderSwitch(geomFSWithShadowSupport); QueueShaderResourceUpdate(geomFSWithShadowSupport, geomFSShadowUnbindPackage); // Set instance buffer and flush all commands, first on immediate context, then on each deferred SetInstanceBufferAndFlushCommands(); pp.InvokeOnAll(setInstanceBufferAndFlushCommandsAct, false); } }
/// <summary> /// Called from the <see cref="LosgapSystem.MasterThread"/> when this render pass should execute. /// Before this method is called, mutations on the <see cref="RenderingModule.RenderStateBarrier"/> are frozen; and will remain frozen /// until this method returns. /// </summary> /// <param name="pp">The parallelization provider currently in use by the system, providing a way to utilise all cores of the system.</param> protected internal abstract void Execute(ParallelizationProvider pp);
protected internal override void Execute(ParallelizationProvider pp) { DepthStencilViewHandle _; if (!output.TargetWindow.GetWindowRTVAndDSV(out windowRTVH, out _)) { return; } List <GeometryCache> activeCaches = GeometryCache.ActiveCaches; foreach (GeometryCache c in activeCaches) { // Set view/proj matrix Matrix vpMat = (*((Matrix *)Input.GetRecalculatedViewMatrix()) * *((Matrix *)Output.GetRecalculatedProjectionMatrix(Input))).Transpose; byte * vpMapPtr = (byte *)&vpMat; VertexShader.ViewProjMatBinding.SetValue(vpMapPtr); // Set state for current cache cpuInstanceBufferCurIndex = 0; List <SceneLayer> allEnabledLayers = Scene.EnabledLayers; uint maxLayer = 0U; for (int i = 0; i < allEnabledLayers.Count; ++i) { if (allEnabledLayers[i].Index > maxLayer) { maxLayer = allEnabledLayers[i].Index; } } if (allEnabledLayers.Count > 0 && currentSceneLayers.Length <= maxLayer) { currentSceneLayers = new SceneLayer[maxLayer + 1U]; } Array.Clear(currentSceneLayers, 0, currentSceneLayers.Length); foreach (SceneLayer layer in allEnabledLayers) { currentSceneLayers[layer.Index] = layer; } currentCache = c; ++frameNum; Thread.MemoryBarrier(); currentInstanceData = currentCache.GetModelInstanceData(); // Set up each thread pp.InvokeOnAll(setUpCacheForLocalThreadAct, true); // also emits a membar // Iterate all model instances (ordered by material) pp.Execute((int)currentInstanceData.Length, (int)(currentInstanceData.Length / (pp.NumThreads << 3)) + 1, renderCacheIterateMatAct); // Set instance buffer and write to it if (gpuInstanceBuffer == null || gpuInstanceBuffer.Length < cpuInstanceBuffer.Length) { if (gpuInstanceBuffer != null) { gpuInstanceBuffer.Dispose(); } gpuInstanceBuffer = gpuInstanceBufferBuilder.WithLength((uint)cpuInstanceBuffer.Length).Create(); } gpuInstanceBuffer.DiscardWrite(cpuInstanceBuffer); // Happens immediately (required) // Set instance buffer and flush all commands, first on immediate context, then on each deferred SetInstanceBufferAndFlushCommands(); pp.InvokeOnAll(setInstanceBufferAndFlushCommandsAct, false); } // Present FlushRenderCommands(); if (presentAfterPass) { PresentBackBuffer(Output.TargetWindow); } }
protected internal override void Execute(ParallelizationProvider pp) { // Set up buffers if (!output.TargetWindow.GetWindowRTVAndDSV(out windowRTVH, out windowDSVH)) { return; } Vector2 viewportSizePixels = output.TargetWindow.AddedViewports.First().SizePixels; if (viewportSizePixels.X <= 0f || viewportSizePixels.Y <= 0f) { return; } SetUpBuffers(viewportSizePixels); // Clear pre-glow buffer QueueRenderCommand(RenderCommand.ClearRenderTarget(preGlowTargetBufferRTV)); QueueRenderCommand(RenderCommand.ClearRenderTarget(glowSrcBufferRTV)); QueueRenderCommand(RenderCommand.ClearRenderTarget(glowDstBufferRTV)); List <GeometryCache> activeCaches = GeometryCache.ActiveCaches; foreach (GeometryCache c in activeCaches) { // Set view/proj matrix Matrix vpMat = (*((Matrix *)Input.GetRecalculatedViewMatrix()) * *((Matrix *)Output.GetRecalculatedProjectionMatrix(Input))).Transpose; byte * vpMapPtr = (byte *)&vpMat; VertexShader.ViewProjMatBinding.SetValue(vpMapPtr); // Set state for current cache cpuInstanceBufferCurIndex = 0; List <SceneLayer> allEnabledLayers = Scene.EnabledLayers; uint maxLayer = 0U; for (int i = 0; i < allEnabledLayers.Count; ++i) { if (allEnabledLayers[i].Index > maxLayer) { maxLayer = allEnabledLayers[i].Index; } } if (allEnabledLayers.Count > 0 && currentSceneLayers.Length <= maxLayer) { currentSceneLayers = new SceneLayer[maxLayer + 1U]; } Array.Clear(currentSceneLayers, 0, currentSceneLayers.Length); foreach (SceneLayer layer in allEnabledLayers) { currentSceneLayers[layer.Index] = layer; } currentCache = c; ++frameNum; Thread.MemoryBarrier(); currentInstanceData = currentCache.GetModelInstanceData(); // Set up each thread SetUpCacheForLocalThread(); // Iterate all model instances (ordered by material && ZIndex) //if (instanceDataSortSpace.Length < currentInstanceData.Length) instanceDataSortSpace = new KeyValuePair<Material, ModelInstanceManager.MIDArray>[currentInstanceData.Length * 2]; //for (int i = 0; i < currentInstanceData.Length; i += 2) { // var a = currentInstanceData[i]; // if (currentInstanceData.Length == i + 1) { // if (currentInstanceData.Length >= 3) { // if (a.Key.ZIndex < instanceDataSortSpace[i - 2].Key.ZIndex) { // instanceDataSortSpace[i] = instanceDataSortSpace[i - 1]; // instanceDataSortSpace[i - 1] = instanceDataSortSpace[i - 2]; // instanceDataSortSpace[i - 2] = a; // } // else if (a.Key.ZIndex < instanceDataSortSpace[i - 1].Key.ZIndex) { // instanceDataSortSpace[i] = instanceDataSortSpace[i - 1]; // instanceDataSortSpace[i - 1] = a; // } // else instanceDataSortSpace[i] = a; // } // else instanceDataSortSpace[i] = a; // } // else { // var b = currentInstanceData[i + 1]; // if (a.Key.ZIndex <= b.Key.ZIndex) { // instanceDataSortSpace[i] = a; // instanceDataSortSpace[i + 1] = b; // } // else { // instanceDataSortSpace[i] = b; // instanceDataSortSpace[i + 1] = a; // } // } //} Array.Sort(currentInstanceData.ContainingArray, 0, (int)currentInstanceData.Length, zIndexComparer); foreach (KeyValuePair <Material, ModelInstanceManager.MIDArray> material in currentInstanceData) { for (int i = 0; i < currentInstanceData.Length; ++i) { if (currentInstanceData[i].Value == material.Value && currentInstanceData[i].Key == material.Key) { RenderCache_IterateMaterial(i); break; } } } // Set instance buffer and write to it if (gpuInstanceBuffer == null || gpuInstanceBuffer.Length < cpuInstanceBuffer.Length) { if (gpuInstanceBuffer != null) { gpuInstanceBuffer.Dispose(); } gpuInstanceBuffer = gpuInstanceBufferBuilder.WithLength((uint)cpuInstanceBuffer.Length).Create(); } gpuInstanceBuffer.DiscardWrite(cpuInstanceBuffer); // Happens immediately (required) // Set instance buffer and flush all commands, first on immediate context, then on each deferred SetInstanceBufferAndFlushCommands(); } ///* ============================================= // * PREPARE FOR GLOW // * ============================================= */ //// Clear glow buffers //QueueRenderCommand(RenderCommand.ClearRenderTarget(glowSrcBufferRTV)); //// Set blend state //QueueRenderCommand(RenderCommand.SetBlendState(glowBlendState)); //// Set topology //QueueRenderCommand(RenderCommand.SetPrimitiveTopology(RenderCommand.DEFAULT_PRIMITIVE_TOPOLOGY)); //// Set input layout //QueueRenderCommand(RenderCommand.SetInputLayout(glowPlaneInputLayout)); //// Enqueue VS commands //QueueShaderSwitch(glowVS); //QueueShaderResourceUpdate(glowVS); ///* ============================================= // * DOWNSCALE TO GLOW SRC BUFFER // * ============================================= */ //// Set up output merger //QueueRenderCommand(RenderCommand.SetRenderTargets(glowDSBufferDSV, glowSrcBufferRTV)); //// Switch to copy shader //QueueShaderSwitch(scaleDownShader); //QueueShaderResourceUpdate(scaleDownShader, scaleDownShaderResPkg); //// Draw fullscreen triangles //QueueRenderCommand(RenderCommand.Draw(0, 3U)); //QueueRenderCommand(RenderCommand.Draw(3, 3U)); //// Unbind resources //QueueShaderResourceUpdate(scaleDownShader, scaleDownShaderResUnbindPkg); ///* ============================================= // * RENDER GLOW // * ============================================= */ //// Set up output merger //QueueRenderCommand(RenderCommand.SetRenderTargets(glowDSBufferDSV, glowDstBufferRTV)); //// Switch to glow shader //QueueShaderSwitch(glowShader); //QueueShaderResourceUpdate(glowShader, glowShaderVResPkg); //// Set blend state //QueueRenderCommand(RenderCommand.SetBlendState(dstMergeBlend)); //// Draw fullscreen triangles //QueueRenderCommand(RenderCommand.Draw(0, 3U)); //QueueRenderCommand(RenderCommand.Draw(3, 3U)); //// Unbind resources //QueueShaderResourceUpdate(glowShader, glowShaderVResUnbindPkg); ///* ============================================= // * UPSCALE TO BACK BUFFER // * ============================================= */ //// Set up output merger //QueueRenderCommand(RenderCommand.SetRenderTargets(output.TargetWindow)); //// Switch to copy shader //QueueShaderSwitch(scaleUpShader); //QueueShaderResourceUpdate(scaleUpShader, scaleUpShaderResPkg); //// Draw fullscreen triangles //QueueRenderCommand(RenderCommand.Draw(0, 3U)); //QueueRenderCommand(RenderCommand.Draw(3, 3U)); //// Unbind resources //QueueShaderResourceUpdate(scaleUpShader, scaleUpShaderResUnbindPkg); // Present FlushRenderCommands(); if (presentAfterPass) { PresentBackBuffer(Output.TargetWindow); } }
/// <summary> /// Called by the <see cref="LosgapSystem"/> when it is time for this module to 'tick'. At this point, the module should execute /// its logic for the current frame. /// </summary> /// <param name="parallelizationProvider">An object that facilitates multithreaded execution of state. Never null.</param> /// <param name="deltaMs">The time, in milliseconds, that has elapsed since the last invocation of this method.</param> void ILosgapModule.PipelineIterate(ParallelizationProvider parallelizationProvider, long deltaMs) { float deltaSecs = deltaMs * 0.001f; bool pausePhysicsLocal; lock (staticMutationLock) { foreach (var toBeAdded in entitiesToBeAdded) { entityList.Add(toBeAdded); } foreach (var toBeRemoved in entitiesToBeRemoved) { entityList.Remove(toBeRemoved); } entitiesToBeRemoved.Clear(); entitiesToBeAdded.Clear(); pausePhysicsLocal = pausePhysics; } if (!pausePhysicsLocal) { PhysicsManager.Tick(deltaSecs); PhysicsManager.GetCollisionPairs(collisionPairList); lock (staticMutationLock) { foreach (KVP <PhysicsBodyHandle, PhysicsBodyHandle> pair in collisionPairList) { if (KeyContainedInCRB(pair.Key)) { Entity other = null; if (KeyContainedInCRB(pair.Value)) { other = collisionReportableBodies[pair.Value]; } else { for (int i = 0; i < entityList.Count; ++i) { if (entityList[i].PhysicsBody == pair.Value) { other = entityList[i]; break; } } } if (other != null) { collisionReportableBodies[pair.Key].TouchDetected(other); } } if (KeyContainedInCRB(pair.Value)) { Entity other = null; if (KeyContainedInCRB(pair.Key)) { other = collisionReportableBodies[pair.Key]; } else { for (int i = 0; i < entityList.Count; ++i) { if (entityList[i].PhysicsBody == pair.Key) { other = entityList[i]; break; } } } if (other != null) { collisionReportableBodies[pair.Value].TouchDetected(other); } } } } } for (int i = 0; i < entityList.Count; ++i) { entityList[i].SynchronizedTick(deltaSecs); } OnPostTick(deltaSecs); elapsedTime += deltaSecs; }
//private static readonly Dictionary<RenderPass, int> passCountDict = new Dictionary<RenderPass, int>(); //private static readonly Dictionary<RenderPass, double> passTimeDict = new Dictionary<RenderPass, double>(); //private static readonly Stopwatch timer = Stopwatch.StartNew(); unsafe void ILosgapModule.PipelineIterate(ParallelizationProvider parallelizationProvider, long deltaMs) { #if CODE_ANALYSIS // Required because for some reason we can't ignore this one in source. Justification: parallelizationProvider will never be null. if (parallelizationProvider == null) { throw new ArgumentNullException("parallelizationProvider"); } #endif openWindowCopySpace.Clear(); for (int i = 0; i < Window.OpenWindows.Count; ++i) { openWindowCopySpace.Add(Window.OpenWindows[i]); } foreach (var win in openWindowCopySpace) { win.HydrateMessagePump(); if (!win.IsClosed) { win.Clear(); // If check because HydrateMessagePump can close the window } } RenderStateBarrier.FreezeMutations(); bool singleThreadedModeEnabled = parallelizationProvider.ForceSingleThreadedMode; try { if (!MtRenderingSupported) { parallelizationProvider.ForceSingleThreadedMode = true; } for (int p = 0; p < activePasses.Count; ++p) { RenderPass currentPass = activePasses[p]; if (!currentPass.IsEnabled) { continue; } if (!currentPass.IsValid) { Logger.Debug(currentPass + " will be skipped as it not in a valid configuration."); continue; } //var timeBefore = timer.Elapsed; currentPass.OnPrePass(); currentPass.Execute(parallelizationProvider); currentPass.OnPostPass(); //if (!passCountDict.ContainsKey(currentPass)) { // passCountDict.Add(currentPass, 0); // passTimeDict.Add(currentPass, 0d); //} //passTimeDict[currentPass] += (timer.Elapsed - timeBefore).TotalMilliseconds; //if (++passCountDict[currentPass] == 1000) { // Logger.Log("Pass '" + currentPass + "' avg time = " + (passTimeDict[currentPass] / 1000d) + "ms"); // passCountDict[currentPass] = 0; // passTimeDict[currentPass] = 0d; //} } } finally { parallelizationProvider.ForceSingleThreadedMode = singleThreadedModeEnabled; RenderStateBarrier.UnfreezeMutations(); } }
protected internal unsafe override void Execute(ParallelizationProvider pp) { // See if we need to resize the depth buffer Vector2 viewportDimensions = output.SizePixels; if (viewportDimensions.X < 1f || viewportDimensions.Y < 1f) { return; } uint viewportX = (uint)viewportDimensions.X; uint viewportY = (uint)viewportDimensions.Y; if (shadowBuffer == null || shadowBufferDSV == null || shadowBufferDSV.ResourceOrViewDisposed || shadowBufferSRV == null || shadowBufferSRV.ResourceOrViewDisposed || shadowBuffer.Width != viewportX || shadowBuffer.Height != viewportY) { if (shadowBufferDSV != null && !shadowBufferDSV.IsDisposed) { shadowBufferDSV.Dispose(); } if (shadowBuffer != null && !shadowBuffer.IsDisposed) { shadowBuffer.Dispose(); } shadowBuffer = shadowBufferBuilder.WithWidth(viewportX).WithHeight(viewportY); shadowBufferDSV = shadowBuffer.CreateDepthStencilView <TexelFormat.DepthStencil>(0U); shadowBufferSRV = shadowBuffer.CreateView <TexelFormat.R24UnormX8Typeless>(0U, 1U); } // Clear the depth buffer QueueRenderCommand(RenderCommand.ClearDepthStencil(shadowBufferDSV)); List <GeometryCache> activeCaches = GeometryCache.ActiveCaches; foreach (GeometryCache c in activeCaches) { // Set view/proj matrix Matrix vpMat = (*((Matrix *)lightCam.GetRecalculatedViewMatrix()) * *((Matrix *)Output.GetRecalculatedProjectionMatrix(lightCam))).Transpose; byte * vpMapPtr = (byte *)&vpMat; shadowVS.ViewProjMatBinding.SetValue(vpMapPtr); // Set state for current cache cpuInstanceBufferCurIndex = 0; List <SceneLayer> allEnabledLayers = Scene.EnabledLayers; uint maxLayer = 0U; for (int i = 0; i < allEnabledLayers.Count; ++i) { if (allEnabledLayers[i].Index > maxLayer) { maxLayer = allEnabledLayers[i].Index; } } if (allEnabledLayers.Count > 0 && currentSceneLayers.Length <= maxLayer) { currentSceneLayers = new SceneLayer[maxLayer + 1U]; } Array.Clear(currentSceneLayers, 0, currentSceneLayers.Length); foreach (SceneLayer layer in allEnabledLayers) { currentSceneLayers[layer.Index] = layer; } currentCache = c; ++frameNum; Thread.MemoryBarrier(); currentInstanceData = currentCache.GetModelInstanceData(); // Set up each thread pp.InvokeOnAll(setUpCacheForLocalThreadAct, true); // membar here // Iterate all model instances (ordered by material) pp.Execute((int)currentInstanceData.Length, (int)(currentInstanceData.Length / (pp.NumThreads << 3)) + 1, renderCacheIterateMatAct); // Set instance buffer and write to it if (gpuInstanceBuffer == null || gpuInstanceBuffer.Length < cpuInstanceBuffer.Length) { if (gpuInstanceBuffer != null) { gpuInstanceBuffer.Dispose(); } gpuInstanceBuffer = gpuInstanceBufferBuilder.WithLength((uint)cpuInstanceBuffer.Length).Create(); } gpuInstanceBuffer.DiscardWrite(cpuInstanceBuffer); // Happens immediately (required) // Set instance buffer and flush all commands, first on immediate context, then on each deferred SetInstanceBufferAndFlushCommands(); pp.InvokeOnAll(setInstanceBufferAndFlushCommandsAct, false); } }