Exemplo n.º 1
0
            public Configure(GpuDevice device, Settings settings, GpuBindGroupLayout bindGroupLayout, GpuBindGroupLayout dynamicBindGroupLayout, GpuBindGroupLayout timeBindGroupLayout, GpuRenderPipeline pipeline, GpuRenderPipeline dynamicPipeline, GpuBuffer vertexBuffer, GpuTextureFormat swapChainFormat)
            {
                Device          = device;
                Settings        = settings;
                Pipeline        = pipeline;
                DynamicPipeline = dynamicPipeline;
                VertexBuffer    = vertexBuffer;
                SwapChainFormat = swapChainFormat;

                UniformBuffer = Device.CreateBuffer(new GpuBufferDescriptor(Settings.NumTriangles * AlignedUniformBytes + sizeof(float), GpuBufferUsageFlags.Uniform | GpuBufferUsageFlags.CopyDst));
                var uniformCpuBuffer = new Windows.Storage.Streams.Buffer(Settings.NumTriangles * AlignedUniformBytes)
                {
                    Length = Settings.NumTriangles * AlignedUniformBytes
                };

                using (var uniformCpuStream = uniformCpuBuffer.AsStream())
                    using (var uniformCpuWriter = new BinaryWriter(uniformCpuStream))
                    {
                        var rand = new Random();
                        for (var i = 0; i < Settings.NumTriangles; ++i)
                        {
                            uniformCpuWriter.Seek((int)(i * AlignedUniformBytes), SeekOrigin.Begin);
                            float scale = (float)(rand.NextDouble() * 0.2 + 0.2);
                            //scale = 5;
                            float offsetX      = (float)(0.9 * 2 * (rand.NextDouble() - 0.5));
                            float offsetY      = (float)(0.9 * 2 * (rand.NextDouble() - 0.5));
                            float scalar       = (float)(rand.NextDouble() * 1.5 + 0.5);
                            float scalarOffset = (float)(rand.NextDouble() * 10);
                            uniformCpuWriter.Write(scale);        //Scale
                            uniformCpuWriter.Write(offsetX);      //offsetX
                            uniformCpuWriter.Write(offsetY);      //offsetY
                            uniformCpuWriter.Write(scalar);       //scalar
                            uniformCpuWriter.Write(scalarOffset); //scalar offset
                        }
                    }
                BindGroups = new GpuBindGroup[Settings.NumTriangles];
                for (var i = 0; i < Settings.NumTriangles; ++i)
                {
                    BindGroups[i] = Device.CreateBindGroup(new GpuBindGroupDescriptor(bindGroupLayout, new GpuBindGroupEntry[]
                    {
                        new GpuBindGroupEntry(0, new GpuBufferBinding(UniformBuffer, 6 * sizeof(float))
                        {
                            Offset = (UInt64)(i * AlignedUniformBytes)
                        })
                    }));
                }
                DynamicBindGroup = Device.CreateBindGroup(new GpuBindGroupDescriptor(dynamicBindGroupLayout, new GpuBindGroupEntry[]
                {
                    new GpuBindGroupEntry(0, new GpuBufferBinding(UniformBuffer, 6 * sizeof(float)))
                }));


                TimeBindGroup = Device.CreateBindGroup(new GpuBindGroupDescriptor(timeBindGroupLayout, new GpuBindGroupEntry[]
                {
                    new GpuBindGroupEntry(0, new GpuBufferBinding(UniformBuffer, sizeof(float))
                    {
                        Offset = TimeOffset
                    })
                }));
                Device.DefaultQueue.WriteBuffer(UniformBuffer, 0, uniformCpuBuffer);
                var renderBundleEncoder = Device.CreateRenderBundleEncoder(new GpuRenderBundleEncoderDescriptor(new GpuTextureFormat[] { SwapChainFormat }));

                RecordRenderPass(renderBundleEncoder);
                RenderBundle         = renderBundleEncoder.Finish();
                UniformTimeCpuBuffer = new Windows.Storage.Streams.Buffer(sizeof(float))
                {
                    Length = sizeof(float)
                };
            }
        async Task Init()
        {
            var adapter = await Gpu.RequestAdapterAsync();

            Device = await adapter.RequestDeviceAsync();

            GpuShaderModule computeShader;

            using (var shaderFileStream = typeof(MainWindow).Assembly.GetManifestResourceStream("ComputeBoidsWpf.compute.hlsl"))
                using (var shaderStreamReader = new StreamReader(shaderFileStream))
                {
                    var shaderCode = await shaderStreamReader.ReadToEndAsync();

                    computeShader = Device.CreateShaderModule(new GpuShaderModuleDescriptor(GpuShaderSourceType.Hlsl, shaderCode));
                }

            GpuShaderModule drawShader;

            using (var shaderFileStream = typeof(MainWindow).Assembly.GetManifestResourceStream("ComputeBoidsWpf.draw.hlsl"))
                using (var shaderStreamReader = new StreamReader(shaderFileStream))
                {
                    var shaderCode = await shaderStreamReader.ReadToEndAsync();

                    drawShader = Device.CreateShaderModule(new GpuShaderModuleDescriptor(GpuShaderSourceType.Hlsl, shaderCode));
                }
            RenderPipeline = Device.CreateRenderPipeline(new GpuRenderPipelineDescriptor(new GpuVertexState(drawShader, "VSMain")
            {
                VertexBuffers = new GpuVertexBufferLayout[]
                {
                    new GpuVertexBufferLayout(4 * 4, new GpuVertexAttribute[]
                    {
                        new GpuVertexAttribute()
                        {
                            Format         = GpuVertexFormat.Float2,
                            Offset         = 0,
                            ShaderLocation = 0
                        },
                        new GpuVertexAttribute()
                        {
                            Format         = GpuVertexFormat.Float2,
                            Offset         = 2 * 4,
                            ShaderLocation = 1
                        }
                    })
                    {
                        StepMode = GpuInputStepMode.Instance
                    },
                    new GpuVertexBufferLayout(2 * 4, new GpuVertexAttribute[]
                    {
                        new GpuVertexAttribute()
                        {
                            Format         = GpuVertexFormat.Float2,
                            Offset         = 0,
                            ShaderLocation = 2
                        }
                    })
                }
            })
            {
                Fragment = new GpuFragmentState(drawShader, "PSMain", new GpuColorTargetState[] { new GpuColorTargetState {
                                                                                                      Format = GpuTextureFormat.BGRA8UNorm, Blend = null, WriteMask = GpuColorWriteFlags.All
                                                                                                  } }),
                Primitive = new GpuPrimitiveState {
                    Topology = GpuPrimitiveTopology.TriangleList, CullMode = GpuCullMode.None, FrontFace = GpuFrontFace.Ccw
                },
                DepthStencilState = new GpuDepthStencilState(GpuTextureFormat.Depth24PlusStencil8)
                {
                    DepthWriteEnabled = true,
                    DepthCompare      = GpuCompareFunction.Less,
                }
            });
            var computeBindGroupLayout = Device.CreateBindGroupLayout(new GpuBindGroupLayoutDescriptor(new GpuBindGroupLayoutEntry[]
            {
                new GpuBindGroupLayoutEntry()
                {
                    Binding    = 0,
                    Visibility = GpuShaderStageFlags.Compute,
                    Buffer     = new GpuBufferBindingLayout()
                    {
                        Type             = GpuBufferBindingType.Uniform,
                        HasDynamicOffset = false,
                        MinBindingSize   = (ulong)(SimParamData.Length * sizeof(float))
                    }
                },
                new GpuBindGroupLayoutEntry()
                {
                    Binding    = 1,
                    Visibility = GpuShaderStageFlags.Compute,
                    Buffer     = new GpuBufferBindingLayout()
                    {
                        Type             = GpuBufferBindingType.ReadOnlyStorage,
                        HasDynamicOffset = false,
                        MinBindingSize   = NumParticles * 16
                    }
                },
                new GpuBindGroupLayoutEntry()
                {
                    Binding    = 2,
                    Visibility = GpuShaderStageFlags.Compute,
                    Buffer     = new GpuBufferBindingLayout()
                    {
                        Type             = GpuBufferBindingType.Storage,
                        HasDynamicOffset = false,
                        MinBindingSize   = NumParticles * 16
                    }
                }
            }));

            ComputePipeline = Device.CreateComputePipeline(new GpuComputePipelineDescriptor(new GpuProgrammableStage(computeShader, "main"))
            {
                Layout = Device.CreatePipelineLayout(new GpuPipelineLayoutDescriptor()
                {
                    BindGroupLayouts = new GpuBindGroupLayout[] { computeBindGroupLayout }
                }),
            });

            VerticesBuffer = Device.CreateBuffer(new GpuBufferDescriptor((ulong)(sizeof(float) * VertexBufferData.Length), GpuBufferUsageFlags.Vertex)
            {
                MappedAtCreation = true
            });
            using (var stream = VerticesBuffer.GetMappedRange().AsStream())
                using (var binaryWriter = new BinaryWriter(stream))
                {
                    for (int i = 0; i < VertexBufferData.Length; ++i)
                    {
                        binaryWriter.Write(VertexBufferData[i]);
                    }
                }
            VerticesBuffer.Unmap();

            var simParamBuffer = Device.CreateBuffer(new GpuBufferDescriptor((ulong)(sizeof(float) * SimParamData.Length), GpuBufferUsageFlags.Uniform)
            {
                MappedAtCreation = true
            });

            using (var stream = simParamBuffer.GetMappedRange().AsStream())
                using (var writer = new BinaryWriter(stream))
                {
                    for (int i = 0; i < SimParamData.Length; ++i)
                    {
                        writer.Write(SimParamData[i]);
                    }
                }
            simParamBuffer.Unmap();

            float[] initialParticleData = new float[NumParticles * 4];
            Random  random = new Random();

            for (var i = 0; i < NumParticles; ++i)
            {
                initialParticleData[4 * i + 0] = (float)(2 * (random.NextDouble() - 0.5f));
                initialParticleData[4 * i + 1] = (float)(2 * (random.NextDouble() - 0.5f));
                initialParticleData[4 * i + 2] = (float)(2 * (random.NextDouble() - 0.5f) * 0.1);
                initialParticleData[4 * i + 3] = (float)(2 * (random.NextDouble() - 0.5f) * 0.1);
            }
            Windows.Storage.Streams.Buffer initialParticleDataBuffer = new Windows.Storage.Streams.Buffer((uint)(sizeof(float) * initialParticleData.Length))
            {
                Length = (uint)(sizeof(float) * initialParticleData.Length)
            };
            using (var stream = initialParticleDataBuffer.AsStream())
                using (var writer = new BinaryWriter(stream))
                {
                    for (int i = 0; i < initialParticleData.Length; ++i)
                    {
                        writer.Write(initialParticleData[i]);
                    }
                }

            ParticleBuffers = new GpuBuffer[2];
            for (int i = 0; i < 2; ++i)
            {
                ParticleBuffers[i] = Device.CreateBuffer(new GpuBufferDescriptor(initialParticleDataBuffer.Length, GpuBufferUsageFlags.Vertex | GpuBufferUsageFlags.Storage)
                {
                    MappedAtCreation = true
                });
                initialParticleDataBuffer.CopyTo(ParticleBuffers[i].GetMappedRange());
                ParticleBuffers[i].Unmap();
            }
            ParticleBindGroups = new GpuBindGroup[2];
            for (var i = 0; i < 2; ++i)
            {
                ParticleBindGroups[i] = Device.CreateBindGroup(new GpuBindGroupDescriptor(computeBindGroupLayout, new GpuBindGroupEntry[]
                {
                    new GpuBindGroupEntry(0, new GpuBufferBinding(simParamBuffer, simParamBuffer.Size)),
                    new GpuBindGroupEntry(1, new GpuBufferBinding(ParticleBuffers[i], ParticleBuffers[i].Size)),
                    new GpuBindGroupEntry(2, new GpuBufferBinding(ParticleBuffers[(i + 1) % 2], ParticleBuffers[(i + 1) % 2].Size))
                }));
            }
            T = 0;
        }