コード例 #1
0
        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
        }
コード例 #2
0
        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
        }
コード例 #3
0
        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
        }
コード例 #4
0
        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
        }
コード例 #5
0
 protected static void QueueRenderCommand(uint reservedCommandSlot, RenderCommand command)
 {
     ThreadLocalRCQ.QueueCommand(reservedCommandSlot, command);
 }
コード例 #6
0
 protected static void QueueRenderCommand(RenderCommand command)
 {
     ThreadLocalRCQ.QueueCommand(command);
 }
コード例 #7
0
        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);
        }
コード例 #8
0
        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);
            }
        }
コード例 #9
0
 internal RCQItem(RenderCommand renderCommand)
 {
     RenderCommand = renderCommand;
     Action        = null;
 }
コード例 #10
0
        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);
        }
コード例 #11
0
        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
        }
コード例 #12
0
        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
        }
コード例 #13
0
        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
        }
コード例 #14
0
        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
        }
コード例 #15
0
 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;
 }
コード例 #16
0
        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);
            }
        }
コード例 #17
0
        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);
            }
        }
コード例 #18
0
        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);
            }
        }