public void TestSetShader() { ConstantBuffer <Matrix> vpMat = BufferFactory.NewConstantBuffer <Matrix>().WithUsage(ResourceUsage.DiscardWrite); VertexShader vs = VertexShader.NewDefaultShader(vpMat); ConstantBuffer <Vector4> colorVec = BufferFactory.NewConstantBuffer <Vector4>().WithUsage(ResourceUsage.DiscardWrite); FragmentShader fs = new FragmentShader(@"Tests\SimpleFS.cso", new ConstantBufferBinding(0U, "MaterialProperties", colorVec)); RenderCommand testCommand = RenderCommand.SetShader(vs); Assert.AreEqual(RenderCommandInstruction.VSSetShader, testCommand.Instruction); Assert.AreEqual((RenderCommandArgument)(IntPtr)vs.Handle, testCommand.Arg1); testCommand = RenderCommand.SetShader(fs); Assert.AreEqual(RenderCommandInstruction.FSSetShader, testCommand.Instruction); Assert.AreEqual((RenderCommandArgument)(IntPtr)fs.Handle, testCommand.Arg1); #if !DEVELOPMENT && !RELEASE try { RenderCommand.SetShader(null); Assert.Fail(); } catch (AssuranceFailedException) { } #endif vs.Dispose(); fs.Dispose(); vpMat.Dispose(); colorVec.Dispose(); #if !DEVELOPMENT && !RELEASE try { RenderCommand.SetShader(fs); Assert.Fail(); } catch (AssuranceFailedException) { } #endif }
public unsafe void SetShaderConstantBuffers() { ConstantBuffer <Vector4> cb0 = BufferFactory.NewConstantBuffer <Vector4>().WithUsage(ResourceUsage.DiscardWrite); ConstantBuffer <Matrix> cb1 = BufferFactory.NewConstantBuffer <Matrix>().WithUsage(ResourceUsage.DiscardWrite); Shader shader = new FragmentShader( @"Tests\SimpleFS.cso", new ConstantBufferBinding(0U, "CB0", cb0), new ConstantBufferBinding(1U, "CB1", cb1) ); RenderCommand testCommand = RenderCommand.SetShaderConstantBuffers(shader); Assert.AreEqual(RenderCommandInstruction.FSSetCBuffers, testCommand.Instruction); ResourceHandle *resHandleArray = (ResourceHandle *)new IntPtr(UnsafeUtils.Reinterpret <RenderCommandArgument, long>(testCommand.Arg1, sizeof(long))); Assert.AreEqual(cb0.ResourceHandle, resHandleArray[0]); Assert.AreEqual(cb1.ResourceHandle, resHandleArray[1]); Assert.AreEqual((RenderCommandArgument)shader.NumConstantBufferSlots, testCommand.Arg2); shader.Dispose(); cb1.Dispose(); cb0.Dispose(); #if !DEVELOPMENT && !RELEASE try { RenderCommand.SetShaderConstantBuffers(null); Assert.Fail(); } catch (AssuranceFailedException) { } try { RenderCommand.SetShaderConstantBuffers(shader); 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 }
public void TestClearRenderTarget() { Texture2D <TexelFormat.RenderTarget> renderTarget = TextureFactory.NewTexture2D <TexelFormat.RenderTarget>() .WithWidth(800U) .WithHeight(600U) .WithDynamicDetail(false) .WithMipAllocation(false) .WithMipGenerationTarget(false) .WithMultisampling(false) .WithPermittedBindings(GPUBindings.RenderTarget) .WithUsage(ResourceUsage.Write); RenderTargetView rtv = renderTarget.CreateRenderTargetView(0U); RenderCommand testCommand = RenderCommand.ClearRenderTarget(rtv); Assert.AreEqual(RenderCommandInstruction.ClearRenderTarget, testCommand.Instruction); Assert.AreEqual((RenderCommandArgument)(IntPtr)(ResourceViewHandle)rtv.ResourceViewHandle, testCommand.Arg1); #if !DEVELOPMENT && !RELEASE try { RenderCommand.ClearRenderTarget(null as RenderTargetView); Assert.Fail(); } catch (AssuranceFailedException) { } #endif rtv.Dispose(); renderTarget.Dispose(); #if !DEVELOPMENT && !RELEASE try { RenderCommand.ClearRenderTarget(rtv); Assert.Fail(); } catch (AssuranceFailedException) { } #endif }
protected static void QueueRenderCommand(uint reservedCommandSlot, RenderCommand command) { ThreadLocalRCQ.QueueCommand(reservedCommandSlot, command); }
protected static void QueueRenderCommand(RenderCommand command) { ThreadLocalRCQ.QueueCommand(command); }
private void RenderCache_IterateMaterial(int materialIndex) { // Set up context variables KeyValuePair <Material, ModelInstanceManager.MIDArray> currentKVP = currentInstanceData[materialIndex]; Material currentMaterial = currentKVP.Key; ModelInstanceManager.MIDArray currentMID = currentKVP.Value; // Skip this material if it or its shader are disposed if (currentMaterial.IsDisposed || currentMaterial.Shader.IsDisposed) { return; } // Skip this material if we're not using it bool inUse = false; for (int i = 0; i < currentMID.Length; ++i) { if (currentMID.Data[i].InUse) { inUse = true; break; } } if (!inUse) { return; } // Prepare shader according to material params, and switch to it or update it if (lastSetFragmentShader != currentMaterial.Shader || lastFrameNum != frameNum) { lastSetFragmentShader = currentMaterial.Shader; lastFrameNum = frameNum; QueueShaderSwitch(lastSetFragmentShader); } var queuedSRP = currentMaterial.FragmentShaderResourcePackage; if (lastSetFragmentShader == geomFSWithShadowSupport) { if (modifiedSRP == null) { modifiedSRP = new ShaderResourcePackage(); } modifiedSRP.CopyFrom(queuedSRP); modifiedSRP.SetValue((ResourceViewBinding)lastSetFragmentShader.GetBindingByIdentifier("ShadowMap"), previousShadowBufferSRV); queuedSRP = modifiedSRP; } QueueShaderResourceUpdate(lastSetFragmentShader, queuedSRP); // Filter & sort if (materialFilteringWorkspace == null || materialFilteringWorkspace.Length < currentCache.NumModels) { materialFilteringWorkspace = new FastClearList <Transform> [currentCache.NumModels]; for (int i = 0; i < materialFilteringWorkspace.Length; ++i) { materialFilteringWorkspace[i] = new FastClearList <Transform>(); } } for (int i = 0; i < materialFilteringWorkspace.Length; ++i) { materialFilteringWorkspace[i].Clear(); } SortByProximityToCamera(currentMID); uint numInstances = 0U; for (uint i = 0U; i < currentMID.Length; ++i) { ModelInstanceData curMID = sortedModelData[i]; if (!curMID.InUse) { continue; } SceneLayer layer = currentSceneLayers[curMID.SceneLayerIndex]; if (layer == null || !layer.GetRenderingEnabled() || !addedSceneLayers.Contains(layer)) { continue; } if (curMID.ModelIndex == __VEGG_MH.ModelIndex && currentCache.ID == __VEGG_MH.GeoCacheID) { int instanceIndex = 0; for (int j = 0; j < currentMID.Length; ++j) { if (currentMID.Data[j].Transform == curMID.Transform) { instanceIndex = j; break; } } Quaternion rot = Quaternion.IDENTITY; foreach (var kvp in __VEGG_MIH_ARR) { if (kvp.Key.InstanceIndex == instanceIndex) { rot = kvp.Value; break; } } materialFilteringWorkspace[curMID.ModelIndex].Add(curMID.Transform.RotateBy(rot)); } else { materialFilteringWorkspace[curMID.ModelIndex].Add(curMID.Transform); } ++numInstances; } // Concatenate & queue render commands if (instanceConcatWorkspace == null || instanceConcatWorkspace.Length < numInstances) { instanceConcatWorkspace = new Matrix[numInstances << 1]; // x2 so we don't create loads of garbage if the count keeps increasing by 1 } uint instanceStartOffset = RenderCache_IterateMaterial_ConcatReserve(numInstances); uint nextWorkspaceIndex = 0; uint outVBStartIndex, outIBStartIndex, outVBCount, outIBCount; for (uint mI = 0U; mI < materialFilteringWorkspace.Length; ++mI) { FastClearList <Transform> filteredTransformList = materialFilteringWorkspace[mI]; int numFilteredTransforms = filteredTransformList.Count; if (numFilteredTransforms == 0) { continue; } currentCache.GetModelBufferValues(mI, out outVBStartIndex, out outIBStartIndex, out outVBCount, out outIBCount); QueueRenderCommand(RenderCommand.DrawIndexedInstanced( (int)outVBStartIndex, outIBStartIndex, outIBCount, nextWorkspaceIndex + instanceStartOffset, (uint)numFilteredTransforms )); for (int iI = 0; iI < numFilteredTransforms; ++iI) { if (mI == __EGGHACK_MH.ModelIndex && currentCache.ID == __EGGHACK_MH.GeoCacheID) { instanceConcatWorkspace[nextWorkspaceIndex++] = filteredTransformList[iI].RotateBy(__EGGHACK_ROT).AsMatrixTransposed; } else { instanceConcatWorkspace[nextWorkspaceIndex++] = filteredTransformList[iI].AsMatrixTransposed; } } } RenderCache_IterateMaterial_Concat(instanceConcatWorkspace, instanceStartOffset, numInstances); }
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); } }
internal RCQItem(RenderCommand renderCommand) { RenderCommand = renderCommand; Action = null; }
private void RenderCache_IterateMaterial(int materialIndex) { // Set up context variables KeyValuePair <Material, ModelInstanceManager.MIDArray> currentKVP = currentInstanceData[materialIndex]; Material currentMaterial = currentKVP.Key; ModelInstanceManager.MIDArray currentMID = currentKVP.Value; // Skip this material if it or its shader are disposed if (currentMaterial.IsDisposed || currentMaterial.Shader.IsDisposed) { return; } // Prepare shader according to material params, and switch to it or update it if (lastSetFragmentShader != currentMaterial.Shader || lastFrameNum != frameNum) { lastSetFragmentShader = currentMaterial.Shader; lastFrameNum = frameNum; QueueShaderSwitch(lastSetFragmentShader); } QueueShaderResourceUpdate(lastSetFragmentShader, currentMaterial.FragmentShaderResourcePackage); // Filter & sort if (materialFilteringWorkspace == null || materialFilteringWorkspace.Length < currentCache.NumModels) { materialFilteringWorkspace = new FastClearList <Transform> [currentCache.NumModels]; for (int i = 0; i < materialFilteringWorkspace.Length; ++i) { materialFilteringWorkspace[i] = new FastClearList <Transform>(); } } for (int i = 0; i < materialFilteringWorkspace.Length; ++i) { materialFilteringWorkspace[i].Clear(); } ModelInstanceData *midData = currentMID.Data; uint numInstances = 0U; for (uint i = 0U; i < currentMID.Length; ++i) { ModelInstanceData curMID = midData[i]; if (!curMID.InUse) { continue; } SceneLayer layer = currentSceneLayers[curMID.SceneLayerIndex]; if (layer == null || !layer.GetRenderingEnabled() || !addedSceneLayers.Contains(layer)) { continue; } materialFilteringWorkspace[curMID.ModelIndex].Add(curMID.Transform); ++numInstances; } // Concatenate & queue render commands if (instanceConcatWorkspace == null || instanceConcatWorkspace.Length < numInstances) { instanceConcatWorkspace = new Matrix[numInstances << 1]; // x2 so we don't create loads of garbage if the count keeps increasing by 1 } uint instanceStartOffset = RenderCache_IterateMaterial_ConcatReserve(numInstances); uint nextWorkspaceIndex = 0; uint outVBStartIndex, outIBStartIndex, outVBCount, outIBCount; for (uint mI = 0U; mI < materialFilteringWorkspace.Length; ++mI) { FastClearList <Transform> filteredTransformList = materialFilteringWorkspace[mI]; int numFilteredTransforms = filteredTransformList.Count; if (numFilteredTransforms == 0) { continue; } currentCache.GetModelBufferValues(mI, out outVBStartIndex, out outIBStartIndex, out outVBCount, out outIBCount); QueueRenderCommand(RenderCommand.DrawIndexedInstanced( (int)outVBStartIndex, outIBStartIndex, outIBCount, nextWorkspaceIndex + instanceStartOffset, (uint)numFilteredTransforms )); for (int iI = 0; iI < numFilteredTransforms; ++iI) { instanceConcatWorkspace[nextWorkspaceIndex++] = filteredTransformList[iI].AsMatrixTransposed; } } RenderCache_IterateMaterial_Concat(instanceConcatWorkspace, instanceStartOffset, numInstances); }
public unsafe void TestSetShaderVertexBuffers() { VertexBufferBuilder <Vector3> vbBuilder = BufferFactory.NewVertexBuffer <Vector3>() .WithLength(100U) .WithUsage(ResourceUsage.DiscardWrite); VertexBuffer <Vector3> vb0 = vbBuilder.Create(); VertexBuffer <Vector2> vb2 = vbBuilder.WithVertexType <Vector2>().Create(); ConstantBuffer <Matrix> vpTransBuffer = BufferFactory.NewConstantBuffer <Matrix>().WithUsage(ResourceUsage.DiscardWrite); VertexShader shader = new VertexShader( @"Tests\SimpleVS.cso", new VertexInputBinding(8U, "Instance"), new ConstantBufferBinding(0U, "VPTB", vpTransBuffer), new VertexInputBinding(0U, "VB0"), new VertexInputBinding(1U, "VB1"), new VertexInputBinding(2U, "VB2") ); Dictionary <VertexInputBinding, IVertexBuffer> vbDict = new Dictionary <VertexInputBinding, IVertexBuffer>(); vbDict[shader.InputBindings[0]] = vb0; vbDict[shader.InputBindings[2]] = vb2; RenderCommand testCommand = RenderCommand.SetShaderVertexBuffers(shader, vbDict); Assert.AreEqual(RenderCommandInstruction.SetVertexBuffers, testCommand.Instruction); ResourceHandle *resHandleArray = (ResourceHandle *)new IntPtr(UnsafeUtils.Reinterpret <RenderCommandArgument, long>(testCommand.Arg1, sizeof(long))); Assert.AreEqual(vb0.ResourceHandle, resHandleArray[0]); Assert.AreEqual(ResourceHandle.NULL, resHandleArray[1]); Assert.AreEqual(vb2.ResourceHandle, resHandleArray[2]); uint *bufferStrideArray = (uint *)new IntPtr(UnsafeUtils.Reinterpret <RenderCommandArgument, long>(testCommand.Arg2, sizeof(long))); Assert.AreEqual((uint)sizeof(Vector3), bufferStrideArray[0]); Assert.AreEqual(0U, bufferStrideArray[1]); Assert.AreEqual((uint)sizeof(Vector2), bufferStrideArray[2]); Assert.AreEqual((RenderCommandArgument)9U, testCommand.Arg3); #if !DEVELOPMENT && !RELEASE try { RenderCommand.SetShaderVertexBuffers(null, vbDict); Assert.Fail(); } catch (AssuranceFailedException) { } try { RenderCommand.SetShaderVertexBuffers(shader, null); Assert.Fail(); } catch (AssuranceFailedException) { } #endif vb0.Dispose(); vb2.Dispose(); vpTransBuffer.Dispose(); vpTransBuffer.Dispose(); #if !DEVELOPMENT && !RELEASE try { RenderCommand.SetShaderVertexBuffers(shader, vbDict); Assert.Fail(); } catch (AssuranceFailedException) { } #endif shader.Dispose(); #if !DEVELOPMENT && !RELEASE try { RenderCommand.SetShaderVertexBuffers(shader, new Dictionary <VertexInputBinding, IVertexBuffer>()); Assert.Fail(); } catch (AssuranceFailedException) { } #endif }
public unsafe void TestSetShaderResourceViews() { Texture2DBuilder <TexelFormat.RGBA32UInt> texBuilder = TextureFactory.NewTexture2D <TexelFormat.RGBA32UInt>() .WithWidth(100U) .WithHeight(100U) .WithUsage(ResourceUsage.DiscardWrite); Texture2D <TexelFormat.RGBA32UInt> tex0 = texBuilder.Create(); Texture2D <TexelFormat.RGBA32UInt> tex2 = texBuilder.Create(); BaseResourceView rv0 = tex0.CreateView(); BaseResourceView rv2 = tex2.CreateView(); Shader shader = new FragmentShader( @"Tests\SimpleFS.cso", new ResourceViewBinding(0U, "RV0"), new ResourceViewBinding(1U, "RV1"), new ResourceViewBinding(2U, "RV2") ); Dictionary <ResourceViewBinding, BaseResourceView> rvDict = new Dictionary <ResourceViewBinding, BaseResourceView>(); rvDict[shader.ResourceViewBindings[0]] = rv0; rvDict[shader.ResourceViewBindings[2]] = rv2; RenderCommand testCommand = RenderCommand.SetShaderResourceViews(shader, rvDict); Assert.AreEqual(RenderCommandInstruction.FSSetResources, testCommand.Instruction); ResourceViewHandle *resHandleArray = (ResourceViewHandle *)new IntPtr(UnsafeUtils.Reinterpret <RenderCommandArgument, long>(testCommand.Arg1, sizeof(long))); Assert.AreEqual(rv0.ResourceViewHandle, resHandleArray[0]); Assert.AreEqual(ResourceViewHandle.NULL, resHandleArray[1]); Assert.AreEqual(rv2.ResourceViewHandle, resHandleArray[2]); Assert.AreEqual((RenderCommandArgument)3U, testCommand.Arg2); #if !DEVELOPMENT && !RELEASE try { RenderCommand.SetShaderResourceViews(null, rvDict); Assert.Fail(); } catch (AssuranceFailedException) { } try { RenderCommand.SetShaderResourceViews(shader, null); Assert.Fail(); } catch (AssuranceFailedException) { } #endif tex0.Dispose(); tex2.Dispose(); rv0.Dispose(); rv2.Dispose(); #if !DEVELOPMENT && !RELEASE try { RenderCommand.SetShaderResourceViews(shader, rvDict); Assert.Fail(); } catch (AssuranceFailedException) { } #endif shader.Dispose(); #if !DEVELOPMENT && !RELEASE try { RenderCommand.SetShaderResourceViews(shader, new Dictionary <ResourceViewBinding, BaseResourceView>()); Assert.Fail(); } catch (AssuranceFailedException) { } #endif }
public unsafe void TestSetShaderTextureSamplers() { TextureSampler ts0 = new TextureSampler(TextureFilterType.Anisotropic, TextureWrapMode.Border, AnisotropicFilteringLevel.EightTimes); TextureSampler ts2 = new TextureSampler(TextureFilterType.Anisotropic, TextureWrapMode.Border, AnisotropicFilteringLevel.EightTimes); Shader shader = new FragmentShader( @"Tests\SimpleFS.cso", new TextureSamplerBinding(0U, "TS0"), new TextureSamplerBinding(1U, "TS1"), new TextureSamplerBinding(2U, "TS2") ); Dictionary <TextureSamplerBinding, TextureSampler> tsDict = new Dictionary <TextureSamplerBinding, TextureSampler>(); tsDict[shader.TextureSamplerBindings[0]] = ts0; tsDict[shader.TextureSamplerBindings[2]] = ts2; RenderCommand testCommand = RenderCommand.SetShaderTextureSamplers(shader, tsDict); Assert.AreEqual(RenderCommandInstruction.FSSetSamplers, testCommand.Instruction); ResourceHandle *resHandleArray = (ResourceHandle *)new IntPtr(UnsafeUtils.Reinterpret <RenderCommandArgument, long>(testCommand.Arg1, sizeof(long))); Assert.AreEqual(ts0.ResourceHandle, resHandleArray[0]); Assert.AreEqual(ResourceHandle.NULL, resHandleArray[1]); Assert.AreEqual(ts2.ResourceHandle, resHandleArray[2]); Assert.AreEqual((RenderCommandArgument)3U, testCommand.Arg2); #if !DEVELOPMENT && !RELEASE try { RenderCommand.SetShaderTextureSamplers(null, tsDict); Assert.Fail(); } catch (AssuranceFailedException) { } try { RenderCommand.SetShaderTextureSamplers(shader, null); Assert.Fail(); } catch (AssuranceFailedException) { } #endif ts0.Dispose(); ts2.Dispose(); #if !DEVELOPMENT && !RELEASE try { RenderCommand.SetShaderTextureSamplers(shader, tsDict); Assert.Fail(); } catch (AssuranceFailedException) { } #endif shader.Dispose(); #if !DEVELOPMENT && !RELEASE try { RenderCommand.SetShaderTextureSamplers(shader, new Dictionary <TextureSamplerBinding, TextureSampler>()); Assert.Fail(); } catch (AssuranceFailedException) { } #endif }
public unsafe void TestSetRenderTargets() { Texture2DArray <TexelFormat.RenderTarget> backBufferArray = TextureFactory.NewTexture2D <TexelFormat.RenderTarget>() .WithWidth(800U) .WithHeight(600U) .WithDynamicDetail(false) .WithMipAllocation(false) .WithMipGenerationTarget(false) .WithMultisampling(false) .WithPermittedBindings(GPUBindings.RenderTarget) .WithUsage(ResourceUsage.Write) .CreateArray(RenderCommand.MAX_RENDER_TARGETS + 1U); Texture2D <TexelFormat.DepthStencil> depthStencil = backBufferArray.Clone() .WithTexelFormat <TexelFormat.DepthStencil>() .WithPermittedBindings(GPUBindings.DepthStencilTarget); RenderTargetView[] rtvArr = backBufferArray.Select(tex => tex.CreateRenderTargetView(0U)).ToArray(); DepthStencilView dsv = depthStencil.CreateDepthStencilView(0U); RenderCommand testCommand = RenderCommand.SetRenderTargets(dsv, rtvArr.Take((int)RenderCommand.MAX_RENDER_TARGETS).ToArray()); Assert.AreEqual(RenderCommandInstruction.SetRenderTargets, testCommand.Instruction); RenderTargetViewHandle *rtvArrPtr = (RenderTargetViewHandle *)new IntPtr(UnsafeUtils.Reinterpret <RenderCommandArgument, long>(testCommand.Arg1, sizeof(long))); for (int i = 0; i < RenderCommand.MAX_RENDER_TARGETS; ++i) { Assert.AreEqual(rtvArr[i].ResourceViewHandle, rtvArrPtr[i]); } Assert.AreEqual( dsv.ResourceViewHandle, UnsafeUtils.Reinterpret <IntPtr, DepthStencilViewHandle>(new IntPtr(UnsafeUtils.Reinterpret <RenderCommandArgument, long>(testCommand.Arg2, sizeof(long))), sizeof(DepthStencilViewHandle)) ); Assert.AreEqual((RenderCommandArgument)RenderCommand.MAX_RENDER_TARGETS, testCommand.Arg3); #if !DEVELOPMENT && !RELEASE try { RenderCommand.SetRenderTargets(null as DepthStencilView, rtvArr.Take((int)RenderCommand.MAX_RENDER_TARGETS).ToArray()); Assert.Fail(); } catch (AssuranceFailedException) { } try { RenderCommand.SetRenderTargets(dsv, null); Assert.Fail(); } catch (AssuranceFailedException) { } try { RenderCommand.SetRenderTargets(dsv, rtvArr[0], rtvArr[1], null, rtvArr[2]); Assert.Fail(); } catch (AssuranceFailedException) { } try { RenderCommand.SetRenderTargets(dsv, rtvArr); Assert.Fail(); } catch (AssuranceFailedException) { } #endif rtvArr.ForEach(rtv => rtv.Dispose()); dsv.Dispose(); backBufferArray.Dispose(); depthStencil.Dispose(); #if !DEVELOPMENT && !RELEASE try { RenderCommand.SetRenderTargets(dsv, rtvArr.Take((int)RenderCommand.MAX_RENDER_TARGETS).ToArray()); Assert.Fail(); } catch (AssuranceFailedException) { } #endif }
public unsafe void QueueCommand(uint reservedCommandSlot, RenderCommand command) { Assure.LessThan(reservedCommandSlot, CurListIndex, "Reserved command slot is outside the range of the list."); ((RenderCommand *)RenderCommandList.AlignedPointer)[reservedCommandSlot] = command; }
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); } }
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 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); } }