public unsafe void TestDepthStencilTargetWithWindow() { Window depthStencilWindow = new Window("Test window"); RenderTargetViewHandle outRTV; DepthStencilViewHandle outDSV; depthStencilWindow.GetWindowRTVAndDSV(out outRTV, out outDSV); RenderCommand testCommand = RenderCommand.ClearDepthStencil(depthStencilWindow); Assert.AreEqual(RenderCommandInstruction.ClearDepthStencil, testCommand.Instruction); Assert.AreEqual( outDSV, UnsafeUtils.Reinterpret <IntPtr, DepthStencilViewHandle>(new IntPtr(UnsafeUtils.Reinterpret <RenderCommandArgument, long>(testCommand.Arg1, sizeof(long))), sizeof(DepthStencilViewHandle)) ); depthStencilWindow.Close(); LosgapSystem.InvokeOnMaster(() => { }); // Wait for the window to be closed testCommand = RenderCommand.ClearDepthStencil(depthStencilWindow); Assert.AreEqual(RenderCommandInstruction.NoOperation, testCommand.Instruction); #if !DEVELOPMENT && !RELEASE try { RenderCommand.ClearDepthStencil(null as Window); Assert.Fail(); } catch (AssuranceFailedException) { } #endif }
public void TestClearDepthStencil() { Texture2D <TexelFormat.DepthStencil> depthStencilBuffer = TextureFactory.NewTexture2D <TexelFormat.DepthStencil>() .WithWidth(800U) .WithHeight(600U) .WithDynamicDetail(false) .WithMipAllocation(false) .WithMipGenerationTarget(false) .WithMultisampling(false) .WithPermittedBindings(GPUBindings.DepthStencilTarget) .WithUsage(ResourceUsage.Write); DepthStencilView dsv = depthStencilBuffer.CreateDepthStencilView(0U); RenderCommand testCommand = RenderCommand.ClearDepthStencil(dsv); Assert.AreEqual(RenderCommandInstruction.ClearDepthStencil, testCommand.Instruction); Assert.AreEqual((RenderCommandArgument)(IntPtr)(ResourceViewHandle)dsv.ResourceViewHandle, testCommand.Arg1); #if !DEVELOPMENT && !RELEASE try { RenderCommand.ClearDepthStencil(null as DepthStencilView); Assert.Fail(); } catch (AssuranceFailedException) { } #endif dsv.Dispose(); depthStencilBuffer.Dispose(); #if !DEVELOPMENT && !RELEASE try { RenderCommand.ClearDepthStencil(dsv); Assert.Fail(); } catch (AssuranceFailedException) { } #endif }
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); } }
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); } }