private void Draw()
        {
            _cl.Begin();
            if (_windowResized)
            {
                _windowResized = false;
                _gd.ResizeMainWindow((uint)_window.Width, (uint)_window.Height);
                _cl.UpdateBuffer(_screenSizeBuffer, 0, new Vector4(_window.Width, _window.Height, 0, 0));
            }

            _cl.SetPipeline(_computePipeline);
            _cl.SetComputeResourceSet(0, _computeResourceSet);
            _cl.SetComputeResourceSet(1, _computeScreenSizeResourceSet);
            _cl.Dispatch(1024, 1, 1);

            _cl.SetFramebuffer(_gd.SwapchainFramebuffer);
            _cl.SetFullViewports();
            _cl.SetFullScissorRects();
            _cl.ClearColorTarget(0, RgbaFloat.Black);
            _cl.SetPipeline(_graphicsPipeline);
            _cl.SetGraphicsResourceSet(0, _graphicsParticleResourceSet);
            _cl.SetGraphicsResourceSet(1, _screenSizeResourceSet);
            _cl.Draw(ParticleCount, 1, 0, 0);
            _cl.End();

            _gd.ExecuteCommands(_cl);
            _gd.SwapBuffers();
        }
예제 #2
0
        private static async Task ExecuteOnGpu(GraphicsDevice device, int index, TestShader shader)
        {
            ShaderGeneratorContext context = new ShaderGeneratorContext(device);

            context.Visit(shader);

            PipelineState pipelineState = await context.CreateComputePipelineStateAsync();

            DescriptorSet?descriptorSet = context.CreateShaderResourceViewDescriptorSet();

            using (CommandList commandList = new CommandList(device, CommandListType.Compute))
            {
                commandList.SetPipelineState(pipelineState);

                if (descriptorSet != null)
                {
                    commandList.SetComputeRootDescriptorTable(0, descriptorSet);
                }

                commandList.Dispatch(1, 1, 1);
                await commandList.FlushAsync();
            }

            float sum = shader.DestinationBuffer.Resource.GetArray <float>().Sum();

            Console.WriteLine($"Origin: GPU, Thread: {index}, sum: {sum}.");
        }
예제 #3
0
        protected override void Draw(float deltaSeconds)
        {
            _cl.Begin();
            _ticks += deltaSeconds * 1000f;
            Vector4 shifts = new Vector4(
                _window.Width * MathF.Cos(_ticks / 500f),   // Red shift
                _window.Height * MathF.Sin(_ticks / 1250f), // Green shift
                MathF.Sin(_ticks / 1000f),                  // Blue shift
                0);                                         // Padding

            _cl.UpdateBuffer(_shiftBuffer, 0, ref shifts);

            _cl.SetPipeline(_computePipeline);
            _cl.SetComputeResourceSet(0, _computeResourceSet);
            _cl.Dispatch((uint)_window.Width, (uint)_window.Height, 1);

            _cl.SetFramebuffer(_gd.SwapchainFramebuffer);
            _cl.SetFullViewports();
            _cl.SetFullScissorRects();
            _cl.ClearColorTarget(0, RgbaFloat.Black);
            _cl.SetPipeline(_graphicsPipeline);
            _cl.SetVertexBuffer(0, _vertexBuffer);
            _cl.SetIndexBuffer(_indexBuffer, IndexFormat.UInt16);
            _cl.SetGraphicsResourceSet(0, _graphicsResourceSet);
            _cl.DrawIndexed(6, 1, 0, 0, 0);

            _cl.End();
            _gd.SubmitCommands(_cl);
            _gd.SwapBuffers();
        }
        protected override void Draw(float deltaSeconds)
        {
            if (!_initialized)
            {
                return;
            }

            _cl.Begin();

            _cl.SetPipeline(_computePipeline);
            _cl.SetComputeResourceSet(0, _computeResourceSet);
            _cl.SetComputeResourceSet(1, _computeScreenSizeResourceSet);
            _cl.Dispatch(1024, 1, 1);

            _cl.SetFramebuffer(MainSwapchain.Framebuffer);
            _cl.SetFullViewports();
            _cl.SetFullScissorRects();
            _cl.ClearColorTarget(0, RgbaFloat.Black);
            _cl.SetPipeline(_graphicsPipeline);
            _cl.SetGraphicsResourceSet(0, _graphicsParticleResourceSet);
            _cl.SetGraphicsResourceSet(1, _screenSizeResourceSet);
            _cl.Draw(ParticleCount, 1, 0, 0);
            _cl.End();

            GraphicsDevice.SubmitCommands(_cl);
            GraphicsDevice.SwapBuffers(MainSwapchain);
        }
        private void DoComputeWork()
        {
            // Reuse the memory associated with command recording.
            // We can only reset when the associated command lists have finished execution on the GPU.
            DirectCmdListAlloc.Reset();

            // A command list can be reset after it has been added to the command queue via ExecuteCommandList.
            // Reusing the command list reuses memory.
            CommandList.Reset(DirectCmdListAlloc, _psos["vecAdd"]);

            CommandList.SetComputeRootSignature(_rootSignature);

            CommandList.SetComputeRootShaderResourceView(0, _inputBufferA.GPUVirtualAddress);
            CommandList.SetComputeRootShaderResourceView(1, _inputBufferB.GPUVirtualAddress);
            CommandList.SetComputeRootUnorderedAccessView(2, _outputBuffer.GPUVirtualAddress);

            CommandList.Dispatch(1, 1, 1);

            // Schedule to copy the data to the default buffer to the readback buffer.
            CommandList.ResourceBarrierTransition(_outputBuffer, ResourceStates.Common, ResourceStates.CopySource);

            CommandList.CopyResource(_readBackBuffer, _outputBuffer);

            CommandList.ResourceBarrierTransition(_outputBuffer, ResourceStates.CopySource, ResourceStates.Common);

            // Done recording commands.
            CommandList.Close();

            // Add the command list to the queue for execution.
            CommandQueue.ExecuteCommandList(CommandList);

            // Wait for the work to finish.
            FlushCommandQueue();

            // Map the data so we can read it on CPU.
            var    mappedData = new Data[NumDataElements];
            IntPtr ptr        = _readBackBuffer.Map(0);

            Utilities.Read(ptr, mappedData, 0, NumDataElements);

            using (var fstream = File.OpenWrite("results.txt"))
            {
                using (var strWriter = new StreamWriter(fstream))
                {
                    foreach (Data data in mappedData)
                    {
                        strWriter.WriteLine($"({data.V1.X}, {data.V1.Y}, {data.V1.Z}, {data.V2.X}, {data.V2.Y})");
                    }
                }
            }

            _readBackBuffer.Unmap(0);
        }
예제 #6
0
        public static async Task RunAsync(GraphicsDevice device)
        {
            int count    = 100;
            int sumCount = 10;

            List <Task> tasks = new List <Task>();

            for (int i = 0; i < count; i++)
            {
                int index = i;

                Console.WriteLine($"Scheduling task {index}");

                tasks.Add(Task.Run(async() =>
                {
                    GraphicsBuffer <float> buffer = GraphicsBuffer.Create <float>(device, sumCount, ResourceFlags.AllowUnorderedAccess);
                    TestShader shader             = new TestShader(buffer, Sigmoid);

                    ShaderGeneratorContext context = new ShaderGeneratorContext(device);
                    context.Visit(shader);

                    ShaderGeneratorResult result = new ShaderGenerator(shader).GenerateShader();

                    PipelineState pipelineState = await context.CreateComputePipelineStateAsync();
                    DescriptorSet?descriptorSet = context.CreateShaderResourceViewDescriptorSet();

                    using (CommandList commandList = new CommandList(device, CommandListType.Compute))
                    {
                        commandList.SetPipelineState(pipelineState);

                        if (descriptorSet != null)
                        {
                            commandList.SetComputeRootDescriptorTable(0, descriptorSet);
                        }

                        commandList.Dispatch(1, 1, 1);
                        await commandList.FlushAsync();
                    }

                    float sum = buffer.GetData().Sum();

                    Console.WriteLine($"Thread: {index}, sum: {sum}.");
                }));
            }

            Console.WriteLine("Awaiting tasks...");
            Console.WriteLine($"Task count: {tasks.Count}");

            await Task.WhenAll(tasks);

            Console.WriteLine("DONE!");
        }
        private void RenderGPU()
        {
            _cl.UpdateBuffer(_sceneParamsBuffer, 0, ref _sceneParams);
            _cl.UpdateBuffer(_rayCountBuffer, 0, new Vector4());
            _cl.SetPipeline(_computePipeline);
            _cl.SetComputeResourceSet(0, _computeSet);
            Debug.Assert(Width % 16 == 0 && Height % 16 == 0);
            uint xCount = Width / 16;
            uint yCount = Height / 16;

            _cl.Dispatch(xCount, yCount, 1);
            _cl.CopyBuffer(_rayCountBuffer, 0, _rayCountReadback, 0, _rayCountBuffer.SizeInBytes);
        }
예제 #8
0
        private void RenderGpu()
        {
            commandList.UpdateBuffer(sceneParamsBuffer, 0, ref Raytracer.SceneParams);
            commandList.UpdateBuffer(rayCountBuffer, 0, new Vector4());
            commandList.SetPipeline(computePipeline);
            commandList.SetComputeResourceSet(0, computeSet);
            Debug.Assert(Window.Width % 16 == 0 && Window.Height % 16 == 0);
            var xCount = (uint)Math.Ceiling(Window.Width / 16d);
            var yCount = (uint)Math.Ceiling(Window.Height / 16d);

            commandList.Dispatch(xCount, yCount, 1);
            commandList.CopyBuffer(rayCountBuffer, 0, rayCountReadback, 0, rayCountBuffer.SizeInBytes);
            Raytracer.SceneParams.FrameCount++;
        }
예제 #9
0
        /// <summary>
        /// Pass the graph plot through the velocity compute shader, to adjust the node velocity based on the positions of other nodes
        /// </summary>
        /// <param name="RSetDesc">Position shader resource set</param>
        /// <param name="cl">Commandlist to run the commands on</param>
        /// <param name="plot">PlottedGraph to compute</param>
        /// <param name="delta">A float representing how much time has passed since the last frame. Higher values => bigger movements</param>
        private void RenderVelocity(ResourceSetDescription RSetDesc, CommandList cl, PlottedGraph plot, float delta)
        {
            //if (GlobalConfig.Settings.Logs.BulkLogging) Logging.RecordLogEvent($"RenderVelocity  {this.EngineID}", Logging.LogFilterType.BulkDebugLogFile);

            _timer.Restart();
            cl.Begin();

            ResourceSet resourceSet = _gd.ResourceFactory.CreateResourceSet(RSetDesc);
            uint        nodeCount   = (uint)plot.RenderedNodeCount();
            //if (GlobalConfig.Settings.Logs.BulkLogging) Logging.RecordLogEvent($"RenderVelocityBlocks  {this.EngineID}", Logging.LogFilterType.BulkDebugLogFile);
            GraphLayoutState     layout     = plot.LayoutState;
            VelocityShaderParams parameters = new VelocityShaderParams
            {
                delta       = delta, //not used
                temperature = Math.Min(plot.Temperature, GlobalConfig.MaximumNodeTemperature),
                repulsionK  = GlobalConfig.RepulsionK,
                nodeCount   = nodeCount
            };

            Debug.Assert(nodeCount <= (layout.VelocitiesVRAM1 !.SizeInBytes / 16));
            //if (GlobalConfig.Settings.Logs.BulkLogging) Logging.RecordLogEvent($"RenderVelocity  {this.EngineID} submit", Logging.LogFilterType.BulkDebugLogFile);

            cl.UpdateBuffer(_velocityParamsBuffer, 0, parameters);
            cl.SetPipeline(_velocityComputePipeline);
            cl.SetComputeResourceSet(0, resourceSet);

            //16 == sizeof(Vector4)
            uint elemCount = layout.VelocitiesVRAM1 !.SizeInBytes / 16;
            uint grpSizeX  = (uint)Math.Ceiling(elemCount / 256.0);

            //Console.WriteLine($"VRAM Size: {layout.VelocitiesVRAM1!.SizeInBytes}bytes, WkX: {grpSizeX}, nodeCount: {nodeCount}, bufVel4Count: {layout.VelocitiesVRAM1!.SizeInBytes/16}");
            cl.Dispatch(grpSizeX, 1, 1);
            //_cl.Dispatch((uint)Math.Ceiling(layout.VelocitiesVRAM1!.SizeInBytes / (256.0 * 16)), 1, 1);
            //if (GlobalConfig.Settings.Logs.BulkLogging) Logging.RecordLogEvent($"RenderVelocity  {this.EngineID} done in {watch.ElapsedMilliseconds} MS", Logging.LogFilterType.BulkDebugLogFile);

            cl.End();
            _timer.Stop();
            VelocitySetupTime = _timer.Elapsed.TotalMilliseconds;

            _timer.Restart();
            _gd !.SubmitCommands(cl);
            _gd !.WaitForIdle();
            _gd.DisposeWhenIdle(resourceSet);

            _timer.Stop();
            VelocityTime = _timer.Elapsed.TotalMilliseconds;
        }
예제 #10
0
        /// <summary>
        /// Dispatches the compute shader and sets the counter value, change per iteration effect parameters right before this call.
        /// </summary>
        public void DrawIteration()
        {
            if (FCompiled && drawCommandList != null && drawRenderDrawContext != null)
            {
                // Apply the effect, TODO: only update parameters here and Apply only once in Draw
                EffectInstance.Apply(drawRenderDrawContext.GraphicsContext);

                // Dispatch compute shader
                if (IsIndirect)
                {
                    drawCommandList.DispatchIndirect(IndirectArgsBuffer, ArgsBufferAlignedByteOffset);
                }
                else
                {
                    drawCommandList.Dispatch(ThreadGroupCounts.X, ThreadGroupCounts.Y, ThreadGroupCounts.Z);
                }
            }
        }
예제 #11
0
        private static async Task ExecuteOnGpu(GraphicsDevice device, StructuredBuffer <float> sourceBufferView, WriteableStructuredBuffer <float> destinationBufferView)
        {
            bool generateWithDelegate = false;

            DescriptorSet descriptorSet = new DescriptorSet(device, 2);

            descriptorSet.AddResourceViews(destinationBufferView);
            descriptorSet.AddResourceViews(sourceBufferView);

            // Generate computer shader
            ShaderGenerator shaderGenerator = generateWithDelegate
                ? CreateShaderGeneratorWithDelegate(sourceBufferView, destinationBufferView)
                : CreateShaderGeneratorWithClass();

            ShaderGeneratorResult result = shaderGenerator.GenerateShader();

            // Compile shader

            byte[] shaderBytecode = ShaderCompiler.Compile(ShaderStage.ComputeShader, result.ShaderSource, result.EntryPoints["compute"]);

            DescriptorRange[] descriptorRanges = new DescriptorRange[]
            {
                new DescriptorRange(DescriptorRangeType.UnorderedAccessView, 1, 0),
                new DescriptorRange(DescriptorRangeType.ShaderResourceView, 1, 0)
            };

            RootParameter rootParameter = new RootParameter(new RootDescriptorTable(descriptorRanges), ShaderVisibility.All);

            RootSignatureDescription rootSignatureDescription = new RootSignatureDescription(RootSignatureFlags.None, new[] { rootParameter });
            RootSignature            rootSignature            = new RootSignature(device, rootSignatureDescription);
            PipelineState            pipelineState            = new PipelineState(device, rootSignature, shaderBytecode);

            // Execute computer shader

            using (CommandList commandList = new CommandList(device, CommandListType.Compute))
            {
                commandList.SetPipelineState(pipelineState);
                commandList.SetComputeRootDescriptorTable(0, descriptorSet);

                commandList.Dispatch(1, 1, 1);
                await commandList.FlushAsync();
            }
        }
예제 #12
0
        private void Draw()
        {
            _cl.Begin();
            if (_windowResized)
            {
                _windowResized = false;
                _gd.ResizeMainWindow((uint)_window.Width, (uint)_window.Height);
                _cl.UpdateBuffer(_screenSizeBuffer, 0, new Vector4(_window.Width, _window.Height, 0, 0));
                CreateWindowSizedResources();
            }

            int     ticks  = Environment.TickCount;
            Vector4 shifts = new Vector4(
                _window.Width * MathF.Cos(ticks / 500f),   // Red shift
                _window.Height * MathF.Sin(ticks / 1250f), // Green shift
                MathF.Sin(ticks / 1000f),                  // Blue shift
                0);                                        // Padding

            _cl.UpdateBuffer(_shiftBuffer, 0, ref shifts);

            _cl.SetPipeline(_computePipeline);
            _cl.SetComputeResourceSet(0, _computeResourceSet);
            _cl.Dispatch((uint)_window.Width, (uint)_window.Height, 1);

            _cl.SetFramebuffer(_gd.SwapchainFramebuffer);
            _cl.SetFullViewports();
            _cl.SetFullScissorRects();
            _cl.ClearColorTarget(0, RgbaFloat.Black);
            _cl.SetPipeline(_graphicsPipeline);
            _cl.SetVertexBuffer(0, _vertexBuffer);
            _cl.SetIndexBuffer(_indexBuffer, IndexFormat.UInt16);
            _cl.SetGraphicsResourceSet(0, _graphicsResourceSet);
            _cl.DrawIndexed(6, 1, 0, 0, 0);

            _cl.End();
            _gd.ExecuteCommands(_cl);
            _gd.SwapBuffers();
        }
예제 #13
0
        /// <summary>
        /// Executes the specified test.
        /// </summary>
        /// <param name="generationResult">The generation result.</param>
        /// <param name="csFunctionName">Name of the cs function.</param>
        /// <param name="output">The output.</param>
        public void Execute(
            ShaderGenerationResult generationResult,
            string csFunctionName,
            ITestOutputHelper output)
        {
            if (Executed)
            {
                output.WriteLine(
                    $"The {Name} tests have already been executed!");
                return;
            }

            TestSets testSets = TestSets;
            Mappings mappings = testSets.Mappings;

            if (ToolChain == null)
            {
                /*
                 * Generate the test data and the result set data for the CPU.
                 */
                AllocateResults(output);
                using (new TestTimer(output,
                                     $"Running {testSets.TestLoops} iterations on the {Name} backend"))
                {
                    for (int test = 0; test < testSets.TestLoops; test++)
                    {
                        foreach (MethodMap method in mappings.MethodMaps)
                        {
                            method.ExecuteCPU(TestSets.TestData, Results, test);
                        }
                    }

                    return;
                }
            }

            GeneratedShaderSet set;
            CompileResult      compilationResult;

            // Compile shader for this backend.
            using (new TestTimer(output, $"Compiling Compute Shader for {ToolChain.GraphicsBackend}"))
            {
                set = generationResult.GetOutput(Backend).Single();
                compilationResult =
                    ToolChain.Compile(set.ComputeShaderCode, Stage.Compute, set.ComputeFunction.Name);
            }

            if (compilationResult.HasError)
            {
                output.WriteLine($"Failed to compile Compute Shader from set \"{set.Name}\"!");
                output.WriteLine(compilationResult.ToString());
                return;
            }

            Assert.NotNull(compilationResult.CompiledOutput);

            using (GraphicsDevice graphicsDevice = ToolChain.CreateHeadless())
            {
                if (!graphicsDevice.Features.ComputeShader)
                {
                    output.WriteLine(
                        $"The {ToolChain.GraphicsBackend} backend does not support compute shaders, skipping!");
                    return;
                }

                ResourceFactory factory = graphicsDevice.ResourceFactory;
                using (DeviceBuffer inOutBuffer = factory.CreateBuffer(
                           new BufferDescription(
                               (uint)mappings.BufferSize,
                               BufferUsage.StructuredBufferReadWrite,
                               (uint)mappings.StructSize)))

                    using (Shader computeShader = factory.CreateShader(
                               new ShaderDescription(
                                   ShaderStages.Compute,
                                   compilationResult.CompiledOutput,
                                   csFunctionName)))

                        using (ResourceLayout inOutStorageLayout = factory.CreateResourceLayout(
                                   new ResourceLayoutDescription(
                                       new ResourceLayoutElementDescription("InOutBuffer", ResourceKind.StructuredBufferReadWrite,
                                                                            ShaderStages.Compute))))

                            using (Pipeline computePipeline = factory.CreateComputePipeline(new ComputePipelineDescription(
                                                                                                computeShader,
                                                                                                new[] { inOutStorageLayout },
                                                                                                1, 1, 1)))


                                using (ResourceSet computeResourceSet = factory.CreateResourceSet(
                                           new ResourceSetDescription(inOutStorageLayout, inOutBuffer)))

                                    using (CommandList commandList = factory.CreateCommandList())
                                    {
                                        // Ensure the headless graphics device is the backend we expect.
                                        Assert.Equal(ToolChain.GraphicsBackend, graphicsDevice.BackendType);

                                        output.WriteLine($"Created compute pipeline for {Name} backend.");

                                        // Allocate the results buffer
                                        AllocateResults(output);

                                        using (new TestTimer(output,
                                                             $"Running {testSets.TestLoops} iterations on the {Name} backend"))
                                        {
                                            // Loop for each test
                                            for (int test = 0; test < testSets.TestLoops; test++)
                                            {
                                                // Update parameter buffer
                                                graphicsDevice.UpdateBuffer(
                                                    inOutBuffer,
                                                    0,
                                                    // Get the portion of test data for the current test loop
                                                    Marshal.UnsafeAddrOfPinnedArrayElement(testSets.TestData, mappings.BufferSize * test),
                                                    (uint)mappings.BufferSize);
                                                graphicsDevice.WaitForIdle();

                                                // Execute compute shaders
                                                commandList.Begin();
                                                commandList.SetPipeline(computePipeline);
                                                commandList.SetComputeResourceSet(0, computeResourceSet);
                                                commandList.Dispatch((uint)mappings.Methods, 1, 1);
                                                commandList.End();

                                                graphicsDevice.SubmitCommands(commandList);
                                                graphicsDevice.WaitForIdle();

                                                // Read back parameters using a staging buffer
                                                using (DeviceBuffer stagingBuffer =
                                                           factory.CreateBuffer(
                                                               new BufferDescription(inOutBuffer.SizeInBytes, BufferUsage.Staging)))
                                                {
                                                    commandList.Begin();
                                                    commandList.CopyBuffer(inOutBuffer, 0, stagingBuffer, 0, stagingBuffer.SizeInBytes);
                                                    commandList.End();
                                                    graphicsDevice.SubmitCommands(commandList);
                                                    graphicsDevice.WaitForIdle();

                                                    // Read back test results
                                                    MappedResource map = graphicsDevice.Map(stagingBuffer, MapMode.Read);

                                                    mappings.SetResults(map.Data, Results, test);
                                                    graphicsDevice.Unmap(stagingBuffer);
                                                }
                                            }
                                        }
                                    }
            }
        }
예제 #14
0
        public void FillBuffer_WithOffsets(uint srcSetMultiple, uint srcBindingMultiple, uint dstSetMultiple, uint dstBindingMultiple, bool combinedLayout)
        {
            if (!GD.Features.ComputeShader)
            {
                return;
            }
            Debug.Assert((GD.StructuredBufferMinOffsetAlignment % sizeof(uint)) == 0);

            uint valueCount        = 512;
            uint dataSize          = valueCount * sizeof(uint);
            uint totalSrcAlignment = GD.StructuredBufferMinOffsetAlignment * (srcSetMultiple + srcBindingMultiple);
            uint totalDstAlignment = GD.StructuredBufferMinOffsetAlignment * (dstSetMultiple + dstBindingMultiple);

            DeviceBuffer copySrc = RF.CreateBuffer(
                new BufferDescription(totalSrcAlignment + dataSize, BufferUsage.StructuredBufferReadOnly, sizeof(uint)));
            DeviceBuffer copyDst = RF.CreateBuffer(
                new BufferDescription(totalDstAlignment + dataSize, BufferUsage.StructuredBufferReadWrite, sizeof(uint)));

            ResourceLayout[] layouts;
            ResourceSet[]    sets;

            DeviceBufferRange srcRange = new DeviceBufferRange(copySrc, srcSetMultiple * GD.StructuredBufferMinOffsetAlignment, dataSize);
            DeviceBufferRange dstRange = new DeviceBufferRange(copyDst, dstSetMultiple * GD.StructuredBufferMinOffsetAlignment, dataSize);

            if (combinedLayout)
            {
                layouts = new[]
                {
                    RF.CreateResourceLayout(new ResourceLayoutDescription(
                                                new ResourceLayoutElementDescription(
                                                    "CopySrc",
                                                    ResourceKind.StructuredBufferReadOnly,
                                                    ShaderStages.Compute,
                                                    ResourceLayoutElementOptions.DynamicBinding),
                                                new ResourceLayoutElementDescription(
                                                    "CopyDst",
                                                    ResourceKind.StructuredBufferReadWrite,
                                                    ShaderStages.Compute,
                                                    ResourceLayoutElementOptions.DynamicBinding)))
                };
                sets = new[]
                {
                    RF.CreateResourceSet(new ResourceSetDescription(layouts[0], srcRange, dstRange))
                };
            }
            else
            {
                layouts = new[]
                {
                    RF.CreateResourceLayout(new ResourceLayoutDescription(
                                                new ResourceLayoutElementDescription(
                                                    "CopySrc",
                                                    ResourceKind.StructuredBufferReadOnly,
                                                    ShaderStages.Compute,
                                                    ResourceLayoutElementOptions.DynamicBinding))),
                    RF.CreateResourceLayout(new ResourceLayoutDescription(
                                                new ResourceLayoutElementDescription(
                                                    "CopyDst",
                                                    ResourceKind.StructuredBufferReadWrite,
                                                    ShaderStages.Compute,
                                                    ResourceLayoutElementOptions.DynamicBinding)))
                };
                sets = new[]
                {
                    RF.CreateResourceSet(new ResourceSetDescription(layouts[0], srcRange)),
                    RF.CreateResourceSet(new ResourceSetDescription(layouts[1], dstRange)),
                };
            }

            Pipeline pipeline = RF.CreateComputePipeline(new ComputePipelineDescription(
                                                             TestShaders.LoadCompute(RF, combinedLayout ? "FillBuffer" : "FillBuffer_SeparateLayout"),
                                                             layouts,
                                                             1, 1, 1));

            uint[] srcData = Enumerable.Range(0, (int)copySrc.SizeInBytes / sizeof(uint)).Select(i => (uint)i).ToArray();
            GD.UpdateBuffer(copySrc, 0, srcData);

            CommandList cl = RF.CreateCommandList();

            cl.Begin();
            cl.SetPipeline(pipeline);
            if (combinedLayout)
            {
                uint[] offsets = new[]
                {
                    srcBindingMultiple *GD.StructuredBufferMinOffsetAlignment,
                       dstBindingMultiple *GD.StructuredBufferMinOffsetAlignment
                };
                cl.SetComputeResourceSet(0, sets[0], offsets);
            }
            else
            {
                uint offset = srcBindingMultiple * GD.StructuredBufferMinOffsetAlignment;
                cl.SetComputeResourceSet(0, sets[0], 1, ref offset);
                offset = dstBindingMultiple * GD.StructuredBufferMinOffsetAlignment;
                cl.SetComputeResourceSet(1, sets[1], 1, ref offset);
            }
            cl.Dispatch(512, 1, 1);
            cl.End();
            GD.SubmitCommands(cl);
            GD.WaitForIdle();

            DeviceBuffer readback = GetReadback(copyDst);

            MappedResourceView <uint> readView = GD.Map <uint>(readback, MapMode.Read);
            for (uint i = 0; i < valueCount; i++)
            {
                uint srcIndex = totalSrcAlignment / sizeof(uint) + i;
                uint expected = srcData[(int)srcIndex];

                uint dstIndex = totalDstAlignment / sizeof(uint) + i;
                uint actual   = readView[dstIndex];

                Assert.Equal(expected, actual);
            }
            GD.Unmap(readback);
        }
예제 #15
0
        public void BasicCompute()
        {
            if (!GD.Features.ComputeShader)
            {
                return;
            }

            ResourceLayout layout = RF.CreateResourceLayout(new ResourceLayoutDescription(
                                                                new ResourceLayoutElementDescription("Params", ResourceKind.UniformBuffer, ShaderStages.Compute),
                                                                new ResourceLayoutElementDescription("Source", ResourceKind.StructuredBufferReadWrite, ShaderStages.Compute),
                                                                new ResourceLayoutElementDescription("Destination", ResourceKind.StructuredBufferReadWrite, ShaderStages.Compute)));

            uint         width             = 1024;
            uint         height            = 1024;
            DeviceBuffer paramsBuffer      = RF.CreateBuffer(new BufferDescription((uint)Unsafe.SizeOf <BasicComputeTestParams>(), BufferUsage.UniformBuffer));
            DeviceBuffer sourceBuffer      = RF.CreateBuffer(new BufferDescription(width * height * 4, BufferUsage.StructuredBufferReadWrite, 4));
            DeviceBuffer destinationBuffer = RF.CreateBuffer(new BufferDescription(width * height * 4, BufferUsage.StructuredBufferReadWrite, 4));

            GD.UpdateBuffer(paramsBuffer, 0, new BasicComputeTestParams {
                Width = width, Height = height
            });

            float[] sourceData = new float[width * height];
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    int index = y * (int)width + x;
                    sourceData[index] = index;
                }
            }
            GD.UpdateBuffer(sourceBuffer, 0, sourceData);

            ResourceSet rs = RF.CreateResourceSet(new ResourceSetDescription(layout, paramsBuffer, sourceBuffer, destinationBuffer));

            Pipeline pipeline = RF.CreateComputePipeline(new ComputePipelineDescription(
                                                             TestShaders.LoadCompute(RF, "BasicComputeTest"),
                                                             layout,
                                                             16, 16, 1));

            CommandList cl = RF.CreateCommandList();

            cl.Begin();
            cl.SetPipeline(pipeline);
            cl.SetComputeResourceSet(0, rs);
            cl.Dispatch(width / 16, width / 16, 1);
            cl.End();
            GD.SubmitCommands(cl);
            GD.WaitForIdle();

            DeviceBuffer sourceReadback      = GetReadback(sourceBuffer);
            DeviceBuffer destinationReadback = GetReadback(destinationBuffer);

            MappedResourceView <float> sourceReadView      = GD.Map <float>(sourceReadback, MapMode.Read);
            MappedResourceView <float> destinationReadView = GD.Map <float>(destinationReadback, MapMode.Read);

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    int index = y * (int)width + x;
                    Assert.Equal(2 * sourceData[index], sourceReadView[index]);
                    Assert.Equal(sourceData[index], destinationReadView[index]);
                }
            }

            GD.Unmap(sourceReadback);
            GD.Unmap(destinationReadback);
        }
예제 #16
0
        public void ComputeShader3dTexture()
        {
            // Just a dumb compute shader that fills a 3D texture with the same value from a uniform multiplied by the depth.
            string shaderText = @"
#version 450
layout(set = 0, binding = 0, rgba32f) uniform image3D TextureToFill;
layout(set = 0, binding = 1) uniform FillValueBuffer
{
    float FillValue;
    float Padding1;
    float Padding2;
    float Padding3;
};
layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
void main()
{
    ivec3 textureCoordinate = ivec3(gl_GlobalInvocationID.xyz);
    float dataToStore = FillValue * (textureCoordinate.z + 1);

    imageStore(TextureToFill, textureCoordinate, vec4(dataToStore));
}
";

            const float FillValue         = 42.42f;
            const uint  OutputTextureSize = 32;

            using Shader computeShader = RF.CreateFromSpirv(new ShaderDescription(
                                                                ShaderStages.Compute,
                                                                Encoding.ASCII.GetBytes(shaderText),
                                                                "main"));

            using ResourceLayout computeLayout = RF.CreateResourceLayout(new ResourceLayoutDescription(
                                                                             new ResourceLayoutElementDescription("TextureToFill", ResourceKind.TextureReadWrite, ShaderStages.Compute),
                                                                             new ResourceLayoutElementDescription("FillValueBuffer", ResourceKind.UniformBuffer, ShaderStages.Compute)));

            using Pipeline computePipeline = RF.CreateComputePipeline(new ComputePipelineDescription(
                                                                          computeShader,
                                                                          computeLayout,
                                                                          16, 16, 1));

            using DeviceBuffer fillValueBuffer = RF.CreateBuffer(new BufferDescription((uint)Marshal.SizeOf <FillValueStruct>(), BufferUsage.UniformBuffer));

            // Create our output texture.
            using Texture computeTargetTexture = RF.CreateTexture(TextureDescription.Texture3D(
                                                                      OutputTextureSize,
                                                                      OutputTextureSize,
                                                                      OutputTextureSize,
                                                                      1,
                                                                      PixelFormat.R32_G32_B32_A32_Float,
                                                                      TextureUsage.Sampled | TextureUsage.Storage));

            using TextureView computeTargetTextureView = RF.CreateTextureView(computeTargetTexture);

            using ResourceSet computeResourceSet = RF.CreateResourceSet(new ResourceSetDescription(
                                                                            computeLayout,
                                                                            computeTargetTextureView,
                                                                            fillValueBuffer));

            using CommandList cl = RF.CreateCommandList();
            cl.Begin();

            cl.UpdateBuffer(fillValueBuffer, 0, new FillValueStruct(FillValue));

            // Use the compute shader to fill the texture.
            cl.SetPipeline(computePipeline);
            cl.SetComputeResourceSet(0, computeResourceSet);
            const uint GroupDivisorXY = 16;

            cl.Dispatch(OutputTextureSize / GroupDivisorXY, OutputTextureSize / GroupDivisorXY, OutputTextureSize);

            cl.End();
            GD.SubmitCommands(cl);
            GD.WaitForIdle();

            // Read back from our texture and make sure it has been properly filled.
            for (uint depth = 0; depth < computeTargetTexture.Depth; depth++)
            {
                RgbaFloat expectedFillValue = new RgbaFloat(new System.Numerics.Vector4(FillValue * (depth + 1)));
                int       notFilledCount    = CountTexelsNotFilledAtDepth(GD, computeTargetTexture, expectedFillValue, depth);

                if (notFilledCount == 0)
                {
                    // Expected behavior:
                    Console.WriteLine($"All texels were properly set at depth {depth}");
                }
                else
                {
                    // Unexpected behavior:
                    uint totalTexels = computeTargetTexture.Width * computeTargetTexture.Height;
                    throw new Exception($"{notFilledCount} of {totalTexels} texels were not properly set at depth {depth}");
                }
            }
        }
예제 #17
0
        private static async Task Main()
        {
            // Create graphics device

            using GraphicsDevice device = new GraphicsDevice(FeatureLevel.Level11_0);

            // Create graphics buffer

            int width  = 10;
            int height = 10;

            float[] array = new float[width * height];

            for (int i = 0; i < array.Length; i++)
            {
                array[i] = i;
            }

            float[] outputArray = new float[width * height];

            using GraphicsBuffer <float> sourceBuffer      = GraphicsBuffer.ShaderResource.New(device, array.AsSpan());
            using GraphicsBuffer <float> destinationBuffer = GraphicsBuffer.UnorderedAccess.New <float>(device, array.Length * 2);

            GraphicsBuffer <float> slicedDestinationBuffer = destinationBuffer.Slice(20, 60);

            slicedDestinationBuffer = slicedDestinationBuffer.Slice(10, 50);

            DescriptorSet descriptorSet = new DescriptorSet(device, 2);

            descriptorSet.AddUnorderedAccessViews(slicedDestinationBuffer);
            descriptorSet.AddShaderResourceViews(sourceBuffer);

            // Generate computer shader

            bool generateWithDelegate = true;

            ShaderGenerator shaderGenerator = generateWithDelegate
                ? CreateShaderGeneratorWithDelegate(sourceBuffer, destinationBuffer)
                : CreateShaderGeneratorWithClass();

            ShaderGeneratorResult result = shaderGenerator.GenerateShader();

            // Copmile shader

            byte[] shaderBytecode = ShaderCompiler.Compile(DxcShaderStage.ComputeShader, result.ShaderSource, result.EntryPoints["compute"]);

            DescriptorRange1[] descriptorRanges = new DescriptorRange1[]
            {
                new DescriptorRange1(DescriptorRangeType.UnorderedAccessView, 1, 0),
                new DescriptorRange1(DescriptorRangeType.ShaderResourceView, 1, 0)
            };

            RootParameter1 rootParameter = new RootParameter1(new RootDescriptorTable1(descriptorRanges), ShaderVisibility.All);

            var rootSignatureDescription = new VersionedRootSignatureDescription(new RootSignatureDescription1(RootSignatureFlags.None, new[] { rootParameter }));
            var rootSignature            = device.CreateRootSignature(rootSignatureDescription);

            PipelineState pipelineState = new PipelineState(device, rootSignature, shaderBytecode);

            // Execute computer shader

            using (CommandList commandList = new CommandList(device, CommandListType.Compute))
            {
                commandList.SetPipelineState(pipelineState);

                commandList.SetComputeRootDescriptorTable(0, descriptorSet);

                commandList.Dispatch(1, 1, 1);
                await commandList.FlushAsync();
            }

            // Print matrix

            Console.WriteLine("Before:");
            PrintMatrix(array, width, height);

            destinationBuffer.GetData(outputArray.AsSpan());

            Console.WriteLine();
            Console.WriteLine("After:");
            PrintMatrix(outputArray, width, height);
        }
예제 #18
0
 public void Dispatch(CommandList cl, uint x, uint y, uint z)
 {
     cl.SetPipeline(Pipeline);
     cl.SetComputeResourceSet(0, ResourceSet);
     cl.Dispatch(x, y, z);
 }
예제 #19
0
        /// <summary>
        /// Update the node attributes compute VRAM buffer (alpha, node size, mouseover details)
        /// </summary>
        /// <param name="cl">Thread-specific CommandList</param>
        /// <param name="graph">ProtoGraph being drawn</param>
        /// <param name="inputAttributes">Attributes buffer being updated</param>
        /// <param name="resources">Shader resources ResourceSet</param>
        /// <param name="delta">Time-delta from the last update</param>
        /// <param name="mouseoverNodeID">Index of the node the mouse is over</param>
        /// <param name="useAnimAttribs">Flag to specify the graph is in animated-alpha mode</param>
        private unsafe void RenderNodeAttribs(CommandList cl, PlottedGraph graph, DeviceBuffer inputAttributes,
                                              ResourceSet resources, float delta, int mouseoverNodeID, bool useAnimAttribs)
        {
            if (GlobalConfig.Settings.Logs.BulkLogging)
            {
                Logging.RecordLogEvent($"RenderNodeAttribs  {this.EngineID}", Logging.LogFilterType.BulkDebugLogFile);
            }
            AttribShaderParams parms = new AttribShaderParams
            {
                delta         = delta,
                hoveredNodeID = mouseoverNodeID,
                nodeCount     = (uint)Math.Min(graph.RenderedNodeCount(), graph.LayoutState.AttributesVRAM1 !.SizeInBytes / 16),
                MinimumAlpha  = GlobalConfig.AnimatedFadeMinimumAlpha,
                hoverMode     = (mouseoverNodeID != -1) ? 1 : 0,
                isAnimated    = useAnimAttribs ? 1: 0
            };


            graph.GetActiveNodeIndexes(out List <uint> pulseNodes, out List <uint> lingerNodes, out uint[] deactivatedNodes);

            if (GlobalConfig.Settings.Logs.BulkLogging)
            {
                Logging.RecordLogEvent($"RenderNodeAttribs {this.EngineID} updating attribsbuf {inputAttributes.Name}", Logging.LogFilterType.BulkDebugLogFile);
            }

            cl.UpdateBuffer(_attribsParamsBuffer, 0, parms);

            float currentPulseAlpha = Math.Max(GlobalConfig.AnimatedFadeMinimumAlpha, GraphicsMaths.getPulseAlpha());

            //todo - merge contiguous regions to reduce command count
            float[] valArray = new float[3];
            foreach (uint idx in pulseNodes)
            {
                if (idx >= graph.RenderedNodeCount())
                {
                    break;
                }

                if (inputAttributes.SizeInBytes <= idx * 4 * sizeof(float) + (2 * sizeof(float)))
                {
                    break;
                }

                valArray[0] = GlobalConfig.NodeSize; //start big
                valArray[1] = 1.0f;                  //full alpha
                valArray[2] = 1.0f;                  //pulse
                fixed(float *dataPtr = valArray)
                {
                    Debug.Assert((idx * 4 * sizeof(float) + valArray.Length * sizeof(float)) < inputAttributes.SizeInBytes);
                    cl.UpdateBuffer(inputAttributes, idx * 4 * sizeof(float), (IntPtr)dataPtr, (uint)valArray.Length * sizeof(float));
                }
            }

            //make the active node pulse
            if (graph.IsAnimated)
            {
                uint activeNodeIdx = graph.LastAnimatedVert;
                if (!lingerNodes.Contains(activeNodeIdx))
                {
                    valArray[0] = currentPulseAlpha;
                    fixed(float *dataPtr = valArray)
                    {
                        uint nodeAlphaOffset = (activeNodeIdx * 4 * sizeof(float)) + (2 * sizeof(float));

                        if (nodeAlphaOffset + sizeof(float) <= inputAttributes.SizeInBytes)
                        {
                            cl.UpdateBuffer(inputAttributes, nodeAlphaOffset, (IntPtr)dataPtr, sizeof(float));
                        }
                    }
                }
            }

            foreach (uint idx in lingerNodes)
            {
                if (idx >= graph.RenderedNodeCount())
                {
                    break;
                }

                if (inputAttributes.SizeInBytes <= idx * 4 * sizeof(float) + (2 * sizeof(float)))
                {
                    break;
                }

                valArray[0] = 2.0f + currentPulseAlpha;
                fixed(float *dataPtr = valArray)
                {
                    Debug.Assert((idx * 4 * sizeof(float) + (2 * sizeof(float)) + sizeof(float)) < inputAttributes.SizeInBytes);
                    cl.UpdateBuffer(inputAttributes, idx * 4 * sizeof(float) + (2 * sizeof(float)), (IntPtr)dataPtr, sizeof(float));
                }
            }

            foreach (uint idx in deactivatedNodes)
            {
                if (idx >= graph.RenderedNodeCount())
                {
                    break;
                }

                if (inputAttributes.SizeInBytes <= idx * 4 * sizeof(float) + (2 * sizeof(float)))
                {
                    break;
                }

                valArray[0] = 0.8f;
                fixed(float *dataPtr = valArray)
                {
                    Debug.Assert((idx * 4 * sizeof(float) + (2 * sizeof(float)) + sizeof(float)) < inputAttributes.SizeInBytes);
                    cl.UpdateBuffer(inputAttributes, idx * 4 * sizeof(float) + (2 * sizeof(float)), (IntPtr)dataPtr, sizeof(float));
                }
            }

            if (graph.HighlightsChanged)
            {
                ApplyHighlightAttributes(cl, graph, inputAttributes);
            }

            cl.SetPipeline(_nodeAttribComputePipeline);
            cl.SetComputeResourceSet(0, resources);

            cl.Dispatch((uint)Math.Ceiling(inputAttributes.SizeInBytes / (256.0 * sizeof(Vector4))), 1, 1);
        }
예제 #20
0
        public void ComputeGeneratedTexture()
        {
            if (!GD.Features.ComputeShader)
            {
                return;
            }

            uint width  = 4;
            uint height = 1;
            TextureDescription texDesc = TextureDescription.Texture2D(
                width, height,
                1,
                1,
                PixelFormat.R32_G32_B32_A32_Float,
                TextureUsage.Sampled | TextureUsage.Storage);
            Texture computeOutput = RF.CreateTexture(texDesc);

            texDesc.Usage = TextureUsage.RenderTarget;
            Texture     finalOutput = RF.CreateTexture(texDesc);
            Framebuffer framebuffer = RF.CreateFramebuffer(new FramebufferDescription(null, finalOutput));

            ResourceLayout computeLayout = RF.CreateResourceLayout(new ResourceLayoutDescription(
                                                                       new ResourceLayoutElementDescription("ComputeOutput", ResourceKind.TextureReadWrite, ShaderStages.Compute)));
            ResourceSet computeSet = RF.CreateResourceSet(new ResourceSetDescription(computeLayout, computeOutput));

            Pipeline computePipeline = RF.CreateComputePipeline(new ComputePipelineDescription(
                                                                    TestShaders.LoadCompute(RF, "ComputeTextureGenerator"),
                                                                    computeLayout,
                                                                    4, 1, 1));

            ResourceLayout graphicsLayout = RF.CreateResourceLayout(new ResourceLayoutDescription(
                                                                        new ResourceLayoutElementDescription("Input", ResourceKind.TextureReadOnly, ShaderStages.Fragment),
                                                                        new ResourceLayoutElementDescription("InputSampler", ResourceKind.Sampler, ShaderStages.Fragment)));
            ResourceSet graphicsSet = RF.CreateResourceSet(new ResourceSetDescription(graphicsLayout, computeOutput, GD.PointSampler));

            Pipeline graphicsPipeline = RF.CreateGraphicsPipeline(new GraphicsPipelineDescription(
                                                                      BlendStateDescription.SingleOverrideBlend,
                                                                      DepthStencilStateDescription.Disabled,
                                                                      RasterizerStateDescription.CullNone,
                                                                      PrimitiveTopology.TriangleStrip,
                                                                      new ShaderSetDescription(
                                                                          Array.Empty <VertexLayoutDescription>(),
                                                                          TestShaders.LoadVertexFragment(RF, "FullScreenBlit")),
                                                                      graphicsLayout,
                                                                      framebuffer.OutputDescription));

            CommandList cl = RF.CreateCommandList();

            cl.Begin();
            cl.SetPipeline(computePipeline);
            cl.SetComputeResourceSet(0, computeSet);
            cl.Dispatch(1, 1, 1);
            cl.SetFramebuffer(framebuffer);
            cl.ClearColorTarget(0, new RgbaFloat());
            cl.SetPipeline(graphicsPipeline);
            cl.SetGraphicsResourceSet(0, graphicsSet);
            cl.Draw(4);
            cl.End();
            GD.SubmitCommands(cl);
            GD.WaitForIdle();

            Texture readback = GetReadback(finalOutput);
            MappedResourceView <RgbaFloat> readView = GD.Map <RgbaFloat>(readback, MapMode.Read);

            Assert.Equal(RgbaFloat.Red, readView[0, 0]);
            Assert.Equal(RgbaFloat.Green, readView[1, 0]);
            Assert.Equal(RgbaFloat.Blue, readView[2, 0]);
            Assert.Equal(RgbaFloat.White, readView[3, 0]);
            GD.Unmap(readback);
        }
예제 #21
0
        public void ComputeGeneratedVertices()
        {
            if (!GD.Features.ComputeShader)
            {
                return;
            }

            uint    width  = 512;
            uint    height = 512;
            Texture output = RF.CreateTexture(
                TextureDescription.Texture2D(width, height, 1, 1, PixelFormat.R32_G32_B32_A32_Float, TextureUsage.RenderTarget));
            Framebuffer framebuffer = RF.CreateFramebuffer(new FramebufferDescription(null, output));

            uint         vertexSize = (uint)Unsafe.SizeOf <ColoredVertex>();
            DeviceBuffer buffer     = RF.CreateBuffer(new BufferDescription(
                                                          vertexSize * 4,
                                                          BufferUsage.StructuredBufferReadWrite,
                                                          vertexSize,
                                                          true));

            ResourceLayout computeLayout = RF.CreateResourceLayout(new ResourceLayoutDescription(
                                                                       new ResourceLayoutElementDescription("OutputVertices", ResourceKind.StructuredBufferReadWrite, ShaderStages.Compute)));
            ResourceSet computeSet = RF.CreateResourceSet(new ResourceSetDescription(computeLayout, buffer));

            Pipeline computePipeline = RF.CreateComputePipeline(new ComputePipelineDescription(
                                                                    TestShaders.LoadCompute(RF, "ComputeColoredQuadGenerator"),
                                                                    computeLayout,
                                                                    1, 1, 1));

            ResourceLayout graphicsLayout = RF.CreateResourceLayout(new ResourceLayoutDescription(
                                                                        new ResourceLayoutElementDescription("InputVertices", ResourceKind.StructuredBufferReadOnly, ShaderStages.Vertex)));
            ResourceSet graphicsSet = RF.CreateResourceSet(new ResourceSetDescription(graphicsLayout, buffer));

            Pipeline graphicsPipeline = RF.CreateGraphicsPipeline(new GraphicsPipelineDescription(
                                                                      BlendStateDescription.SingleOverrideBlend,
                                                                      DepthStencilStateDescription.Disabled,
                                                                      RasterizerStateDescription.Default,
                                                                      PrimitiveTopology.TriangleStrip,
                                                                      new ShaderSetDescription(
                                                                          Array.Empty <VertexLayoutDescription>(),
                                                                          TestShaders.LoadVertexFragment(RF, "ColoredQuadRenderer")),
                                                                      graphicsLayout,
                                                                      framebuffer.OutputDescription));

            CommandList cl = RF.CreateCommandList();

            cl.Begin();
            cl.SetPipeline(computePipeline);
            cl.SetComputeResourceSet(0, computeSet);
            cl.Dispatch(1, 1, 1);
            cl.SetFramebuffer(framebuffer);
            cl.ClearColorTarget(0, new RgbaFloat());
            cl.SetPipeline(graphicsPipeline);
            cl.SetGraphicsResourceSet(0, graphicsSet);
            cl.Draw(4);
            cl.End();
            GD.SubmitCommands(cl);
            GD.WaitForIdle();

            Texture readback = GetReadback(output);
            MappedResourceView <RgbaFloat> readView = GD.Map <RgbaFloat>(readback, MapMode.Read);

            for (uint y = 0; y < height; y++)
            {
                for (uint x = 0; x < width; x++)
                {
                    Assert.Equal(RgbaFloat.Red, readView[x, y]);
                }
            }
            GD.Unmap(readback);
        }
예제 #22
0
        void ILowLevelAPIRender.Draw(RenderContext renderContext, RenderDrawContext drawContext, RenderView renderView, RenderViewStage renderViewStage, CommandList commandList)
        {
            if (!enabledPin.Value)
            {
                return;
            }

            try
            {
                var pipelineState = this.pipelineState ?? (this.pipelineState = new MutablePipelineState(renderContext.GraphicsDevice));

                // TODO1: PerFrame could be done in Update if we'd have access to frame time
                // TODO2: This code can be optimized by using parameter accessors and not parameter keys
                parameters.SetPerFrameParameters(perFrameParams, drawContext.RenderContext);
                parameters.SetPerViewParameters(perViewParams, renderView);

                if (worldPin != null)
                {
                    var world = worldPin.ShaderValue;
                    parameters.SetPerDrawParameters(perDrawParams, renderView, ref world);
                }

                // Set permutation parameters before updating the effect (needed by compiler)
                parameters.Set(ComputeEffectShaderKeys.ThreadNumbers, threadNumbersPin.Value);

                // Give user chance to override
                parameterSetterPin?.Value.Invoke(parameters, renderView, drawContext);

                if (instance.UpdateEffect(renderContext.GraphicsDevice) || pipelineStateDirty)
                {
                    threadGroupCountAccessor = parameters.GetAccessor(ComputeShaderBaseKeys.ThreadGroupCountGlobal);
                    foreach (var p in Inputs.OfType <ParameterPin>())
                    {
                        p.Update(parameters);
                    }
                    pipelineState.State.SetDefaults();
                    pipelineState.State.RootSignature  = instance.RootSignature;
                    pipelineState.State.EffectBytecode = instance.Effect.Bytecode;
                    pipelineState.Update();
                    pipelineStateDirty = false;
                }

                // Apply pipeline state
                commandList.SetPipelineState(pipelineState.CurrentState);

                // Set thread group count as provided by input pin
                var threadGroupCount = dispatchCountPin.Value;
                parameters.Set(ComputeShaderBaseKeys.ThreadGroupCountGlobal, threadGroupCount);

                // TODO: This can be optimized by uploading only parameters from the PerDispatch groups - look in Xenkos RootEffectRenderFeature
                var iterationCount = Math.Max(iterationCountPin.Value, 1);
                for (int i = 0; i < iterationCount; i++)
                {
                    // Give user chance to override
                    iterationParameterSetterPin.Value?.Invoke(parameters, renderView, drawContext, i);

                    // The thread group count can be set for each dispatch
                    threadGroupCount = parameters.Get(threadGroupCountAccessor);

                    // Upload the parameters
                    instance.Apply(drawContext.GraphicsContext);

                    // Draw a full screen quad
                    commandList.Dispatch(threadGroupCount.X, threadGroupCount.Y, threadGroupCount.Z);
                }
            }
            catch (Exception e)
            {
                var re = new RuntimeException(e.InnermostException(), this);
                RuntimeGraph.ReportException(re);
            }
        }