Beispiel #1
0
        private unsafe bool SetupComputeResources()
        {
            Debug.Assert(_gd is not null, "Init not called");
            ResourceFactory factory = _gd.ResourceFactory;

            if (_gd.Features.ComputeShader is false)
            {
                Logging.RecordError("Error: Compute shaders are unavailable"); return(false);
            }

            byte[]? noteattribShaderBytes = ImGuiController.LoadEmbeddedShaderCode(factory, "sim-nodeAttrib", ShaderStages.Vertex);
            _nodeAttribShader             = factory.CreateShader(new ShaderDescription(ShaderStages.Fragment, noteattribShaderBytes, "FS"));

            _nodeAttribComputeLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
                                                                        new ResourceLayoutElementDescription("Params", ResourceKind.UniformBuffer, ShaderStages.Compute),
                                                                        new ResourceLayoutElementDescription("nodeAttrib", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
                                                                        new ResourceLayoutElementDescription("edgeIndices", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
                                                                        new ResourceLayoutElementDescription("edgeData", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
                                                                        new ResourceLayoutElementDescription("resultData", ResourceKind.StructuredBufferReadWrite, ShaderStages.Compute)));
            _attribsParamsBuffer = VeldridGraphBuffers.TrackedVRAMAlloc(_gd, (uint)Unsafe.SizeOf <AttribShaderParams>(), BufferUsage.UniformBuffer, name: "AttribShaderParams");

            ComputePipelineDescription attribCPL = new ComputePipelineDescription(_nodeAttribShader, _nodeAttribComputeLayout, 16, 16, 1);

            _nodeAttribComputePipeline = factory.CreateComputePipeline(attribCPL);
            return(true);
        }
Beispiel #2
0
 public OpenGLPipeline(OpenGLGraphicsDevice gd, ref ComputePipelineDescription description)
 {
     _gd = gd;
     IsComputePipeline  = true;
     ComputeDescription = description;
     VertexStrides      = Array.Empty <int>();
 }
        public override Pipeline CreateComputePipeline(ref ComputePipelineDescription description)
        {
            OpenGLPipeline pipeline = new OpenGLPipeline(_gd, ref description);

            _gd.EnsureResourceInitialized(pipeline);
            return(pipeline);
        }
        private unsafe void SetupComputeResources()
        {
            ResourceFactory factory = _gd.ResourceFactory;

            if (_gd.Features.ComputeShader is false)
            {
                Logging.RecordError("Error: Compute shaders are unavailable"); return;
            }

            _velocityParamsBuffer = VeldridGraphBuffers.TrackedVRAMAlloc(_gd, (uint)Unsafe.SizeOf <VelocityShaderParams>(), BufferUsage.UniformBuffer, name: "VelocityShaderParams");

            byte[]? velocityShaderBytes = ImGuiNET.ImGuiController.LoadEmbeddedShaderCode(factory, "sim-nodeVelocity", ShaderStages.Compute);
            _velocityShader             = factory.CreateShader(new ShaderDescription(ShaderStages.Compute, velocityShaderBytes, "main"));

            _velocityShaderRsrcLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
                                                                         new ResourceLayoutElementDescription("Params", ResourceKind.UniformBuffer, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("positions", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("velocities", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("edgeIndices", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("edgeData", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("edgeStrengths", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("resultData", ResourceKind.StructuredBufferReadWrite, ShaderStages.Compute)));

            ComputePipelineDescription VelocityCPD = new ComputePipelineDescription(_velocityShader, _velocityShaderRsrcLayout, 16, 16, 1); //todo: i dont understand this. experiment with group sizes.

            _velocityComputePipeline = factory.CreateComputePipeline(VelocityCPD);


            _positionShaderRsrcLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
                                                                         new ResourceLayoutElementDescription("Params", ResourceKind.UniformBuffer, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("positions", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("velocities", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("resultData", ResourceKind.StructuredBufferReadWrite, ShaderStages.Compute)
                                                                         ));


            byte[]? positionShaderBytes;

            /*
             * This is how we would compile the compute shaders instead of loading pre-compiled
             * 177ms~ ish for this simple shader - multiplied by the different pipelines and stages this would add a lot to startup time
             *   so for now going to keep embedding them in resources. This at least illustrates how to do startup-time compilation.
             */
            /*
             * if (velocityShaderBytes is null)
             * {
             *  _timer.Restart();
             *  positionShaderBytes = Veldrid.SPIRV.SpirvCompilation.CompileGlslToSpirv(positionShaderSource, null, ShaderStages.Compute, Veldrid.SPIRV.GlslCompileOptions.Default).SpirvBytes;
             *  _timer.Stop();
             *  Logging.RecordLogEvent($"Compilation for ForceDirectedNode Position shader took {_timer.Elapsed.TotalMilliseconds:F1}ms");
             * }
             */
            positionShaderBytes = ImGuiNET.ImGuiController.LoadEmbeddedShaderCode(factory, "sim-nodePosition", ShaderStages.Compute);

            _positionShader = factory.CreateShader(new ShaderDescription(ShaderStages.Compute, positionShaderBytes, "main"));
            ComputePipelineDescription PositionCPD = new ComputePipelineDescription(_positionShader, _positionShaderRsrcLayout, 16, 16, 1);

            _positionComputePipeline = factory.CreateComputePipeline(PositionCPD);
            _positionParamsBuffer    = VeldridGraphBuffers.TrackedVRAMAlloc(_gd, (uint)Unsafe.SizeOf <PositionShaderParams>(), BufferUsage.UniformBuffer, name: "PositionShaderParams");
        }
Beispiel #5
0
        public override Pipeline CreateComputePipeline(ref ComputePipelineDescription description)
        {
            Pipeline pipeline = Factory.CreateComputePipeline(ref description);

            DisposeCollector.Add(pipeline);
            return(pipeline);
        }
Beispiel #6
0
 public OpenGLPipeline(OpenGLGraphicsDevice gd, ref ComputePipelineDescription description)
     : base(ref description)
 {
     _gd = gd;
     IsComputePipeline = true;
     ComputeShader     = description.ComputeShader;
     VertexStrides     = Array.Empty <int>();
     ResourceLayouts   = Util.ShallowClone(description.ResourceLayouts);
 }
Beispiel #7
0
 public D3D11Pipeline(D3D11ResourceCache cache, ref ComputePipelineDescription description)
 {
     IsComputePipeline = true;
     ComputeShader     = (ComputeShader)((D3D11Shader)description.ComputeShader).DeviceShader;
     ResourceLayout[] genericLayouts = description.ResourceLayouts;
     ResourceLayouts = new D3D11ResourceLayout[genericLayouts.Length];
     for (int i = 0; i < ResourceLayouts.Length; i++)
     {
         ResourceLayouts[i] = Util.AssertSubtype <ResourceLayout, D3D11ResourceLayout>(genericLayouts[i]);
     }
 }
Beispiel #8
0
        public ComputeUnit(ResourceFactory factory, Description d) : base(factory, d)
        {
            Shader     = d.Shader;
            xGroupSize = d.xGroupSize;
            yGroupSize = d.yGroupSize;
            zGroupSize = d.zGroupSize;

            ComputePipelineDescription pipelineDescription =
                new ComputePipelineDescription(Shader, Layout, xGroupSize, yGroupSize, zGroupSize);

            Pipeline = factory.CreateComputePipeline(pipelineDescription);
        }
        private unsafe void SetupComputeResources()
        {
            Debug.Assert(_gd is not null, "Init not called");
            ResourceFactory factory = _gd.ResourceFactory;

            if (_gd.Features.ComputeShader is false)
            {
                Logging.RecordError("Error: Compute shaders are unavailable"); return;
            }

            _velocityParamsBuffer = VeldridGraphBuffers.TrackedVRAMAlloc(_gd, (uint)Unsafe.SizeOf <VelocityShaderParams>(), BufferUsage.UniformBuffer, name: "VelocityShaderParams");


            byte[]? velocityBlockShaderBytes = ImGuiNET.ImGuiController.LoadEmbeddedShaderCode(factory, "sim-blockVelocity", ShaderStages.Fragment);
            _velocityShader = factory.CreateShader(new ShaderDescription(ShaderStages.Compute, velocityBlockShaderBytes, "FS"));

            _velocityShaderRsrcLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
                                                                         new ResourceLayoutElementDescription("Params", ResourceKind.UniformBuffer, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("positions", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("velocities", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("edgeIndices", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("edgeData", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("edgeStrengths", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("blockData", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("blockMiddles", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("resultData", ResourceKind.StructuredBufferReadWrite, ShaderStages.Compute)));

            ComputePipelineDescription VelocityBlockCPD = new ComputePipelineDescription(_velocityShader, _velocityShaderRsrcLayout, 16, 16, 1);

            _velocityComputePipeline = factory.CreateComputePipeline(VelocityBlockCPD);

            _positionShaderRsrcLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
                                                                         new ResourceLayoutElementDescription("Params", ResourceKind.UniformBuffer, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("positions", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("velocities", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("blockData", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("resultData", ResourceKind.StructuredBufferReadWrite, ShaderStages.Compute)
                                                                         ));


            byte[]? positionShaderBytes = ImGuiNET.ImGuiController.LoadEmbeddedShaderCode(factory, "sim-blockPosition", ShaderStages.Vertex);
            _positionShader             = factory.CreateShader(new ShaderDescription(ShaderStages.Fragment, positionShaderBytes, "FS")); //todo ... not fragment

            ComputePipelineDescription PositionCPD = new ComputePipelineDescription(_positionShader, _positionShaderRsrcLayout, 16, 16, 1);

            _positionComputePipeline = factory.CreateComputePipeline(PositionCPD);
            _positionParamsBuffer    = VeldridGraphBuffers.TrackedVRAMAlloc(_gd, (uint)Unsafe.SizeOf <PositionShaderParams>(), BufferUsage.UniformBuffer, name: "PositionShaderParams");
        }
Beispiel #10
0
        public MTLPipeline(ref ComputePipelineDescription description, MTLGraphicsDevice gd)
            : base(ref description)
        {
            IsComputePipeline = true;
            ResourceLayouts   = new MTLResourceLayout[description.ResourceLayouts.Length];
            for (int i = 0; i < ResourceLayouts.Length; i++)
            {
                ResourceLayouts[i] = Util.AssertSubtype <ResourceLayout, MTLResourceLayout>(description.ResourceLayouts[i]);
            }

            ThreadsPerThreadgroup = new MTLSize(
                description.ThreadGroupSizeX,
                description.ThreadGroupSizeY,
                description.ThreadGroupSizeZ);

            MTLComputePipelineDescriptor mtlDesc = MTLUtil.AllocInit <MTLComputePipelineDescriptor>(
                nameof(MTLComputePipelineDescriptor));
            MTLShader mtlShader = Util.AssertSubtype <Shader, MTLShader>(description.ComputeShader);

            mtlDesc.computeFunction = mtlShader.Function;
            MTLPipelineBufferDescriptorArray buffers = mtlDesc.buffers;
            uint bufferIndex = 0;

            foreach (MTLResourceLayout layout in ResourceLayouts)
            {
                foreach (ResourceKind kind in layout.ResourceKinds)
                {
                    if (kind == ResourceKind.UniformBuffer ||
                        kind == ResourceKind.StructuredBufferReadOnly)
                    {
                        MTLPipelineBufferDescriptor bufferDesc = buffers[bufferIndex];
                        bufferDesc.mutability = MTLMutability.Immutable;
                        bufferIndex          += 1;
                    }
                    else if (kind == ResourceKind.StructuredBufferReadWrite)
                    {
                        MTLPipelineBufferDescriptor bufferDesc = buffers[bufferIndex];
                        bufferDesc.mutability = MTLMutability.Mutable;
                        bufferIndex          += 1;
                    }
                }
            }

            ComputePipelineState = gd.Device.newComputePipelineStateWithDescriptor(mtlDesc);

            ObjectiveCRuntime.release(mtlDesc.NativePtr);
        }
Beispiel #11
0
        public VkPipeline(VkGraphicsDevice gd, ref ComputePipelineDescription description)
            : base(ref description)
        {
            _gd = gd;
            IsComputePipeline = true;

            VkComputePipelineCreateInfo pipelineCI = VkComputePipelineCreateInfo.New();

            // Pipeline Layout
            ResourceLayout[]           resourceLayouts  = description.ResourceLayouts;
            VkPipelineLayoutCreateInfo pipelineLayoutCI = VkPipelineLayoutCreateInfo.New();

            pipelineLayoutCI.setLayoutCount = (uint)resourceLayouts.Length;
            VkDescriptorSetLayout *dsls = stackalloc VkDescriptorSetLayout[resourceLayouts.Length];

            for (int i = 0; i < resourceLayouts.Length; i++)
            {
                dsls[i] = Util.AssertSubtype <ResourceLayout, VkResourceLayout>(resourceLayouts[i]).DescriptorSetLayout;
            }
            pipelineLayoutCI.pSetLayouts = dsls;

            vkCreatePipelineLayout(_gd.Device, ref pipelineLayoutCI, null, out _pipelineLayout);
            pipelineCI.layout = _pipelineLayout;

            // Shader Stage
            Shader   shader   = description.ComputeShader;
            VkShader vkShader = Util.AssertSubtype <Shader, VkShader>(shader);
            VkPipelineShaderStageCreateInfo stageCI = VkPipelineShaderStageCreateInfo.New();

            stageCI.module   = vkShader.ShaderModule;
            stageCI.stage    = VkFormats.VdToVkShaderStages(shader.Stage);
            stageCI.pName    = CommonStrings.main; // Meh
            pipelineCI.stage = stageCI;

            VkResult result = vkCreateComputePipelines(
                _gd.Device,
                VkPipelineCache.Null,
                1,
                ref pipelineCI,
                null,
                out _devicePipeline);

            CheckResult(result);

            ResourceSetCount = (uint)description.ResourceLayouts.Length;
        }
Beispiel #12
0
        private unsafe void SetupComputeResources()
        {
            ResourceFactory factory = _gd.ResourceFactory;

            if (_gd.Features.ComputeShader is false)
            {
                Logging.RecordError("Error: Compute shaders are unavailable"); return;
            }

            _velocityParamsBuffer = VeldridGraphBuffers.TrackedVRAMAlloc(_gd, (uint)Unsafe.SizeOf <VelocityShaderParams>(), BufferUsage.UniformBuffer, name: "VelocityShaderParams");

            byte[]? velocityShaderBytes = ImGuiNET.ImGuiController.LoadEmbeddedShaderCode(factory, "sim-presetVelocity", ShaderStages.Compute);
            _velocityShader             = factory.CreateShader(new ShaderDescription(ShaderStages.Compute, velocityShaderBytes, "main"));

            _velocityShaderRsrcLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
                                                                         new ResourceLayoutElementDescription("Params", ResourceKind.UniformBuffer, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("positions", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("presetPositions", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("velocities", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("resultData", ResourceKind.StructuredBufferReadWrite, ShaderStages.Compute)));

            ComputePipelineDescription VelocityCPD = new ComputePipelineDescription(_velocityShader, _velocityShaderRsrcLayout, 16, 16, 1); //todo: i dont understand this. experiment with group sizes.

            _velocityComputePipeline = factory.CreateComputePipeline(VelocityCPD);


            _positionShaderRsrcLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
                                                                         new ResourceLayoutElementDescription("Params", ResourceKind.UniformBuffer, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("positions", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("velocities", ResourceKind.StructuredBufferReadOnly, ShaderStages.Compute),
                                                                         new ResourceLayoutElementDescription("resultData", ResourceKind.StructuredBufferReadWrite, ShaderStages.Compute)
                                                                         ));

            byte[]? positionShaderBytes;

            positionShaderBytes = ImGuiNET.ImGuiController.LoadEmbeddedShaderCode(factory, "sim-nodePosition", ShaderStages.Compute);

            _positionShader = factory.CreateShader(new ShaderDescription(ShaderStages.Compute, positionShaderBytes, "main"));
            ComputePipelineDescription PositionCPD = new ComputePipelineDescription(_positionShader, _positionShaderRsrcLayout, 16, 16, 1);

            _positionComputePipeline = factory.CreateComputePipeline(PositionCPD);
            _positionParamsBuffer    = VeldridGraphBuffers.TrackedVRAMAlloc(_gd, (uint)Unsafe.SizeOf <PositionShaderParams>(), BufferUsage.UniformBuffer, name: "PositionShaderParams");
        }
Beispiel #13
0
        public VkPipeline(VkGraphicsDevice gd, ref ComputePipelineDescription description)
            : base(ref description)
        {
            _gd = gd;
            IsComputePipeline = true;
            RefCount          = new ResourceRefCount(DisposeCore);

            VkComputePipelineCreateInfo pipelineCI = VkComputePipelineCreateInfo.New();

            // Pipeline Layout
            ResourceLayout[]           resourceLayouts  = description.ResourceLayouts;
            VkPipelineLayoutCreateInfo pipelineLayoutCI = VkPipelineLayoutCreateInfo.New();

            pipelineLayoutCI.setLayoutCount = (uint)resourceLayouts.Length;
            VkDescriptorSetLayout *dsls = stackalloc VkDescriptorSetLayout[resourceLayouts.Length];

            for (int i = 0; i < resourceLayouts.Length; i++)
            {
                dsls[i] = Util.AssertSubtype <ResourceLayout, VkResourceLayout>(resourceLayouts[i]).DescriptorSetLayout;
            }
            pipelineLayoutCI.pSetLayouts = dsls;

            vkCreatePipelineLayout(_gd.Device, ref pipelineLayoutCI, null, out _pipelineLayout);
            pipelineCI.layout = _pipelineLayout;

            // Shader Stage

            VkSpecializationInfo specializationInfo;

            SpecializationConstant[] specDescs = description.Specializations;
            if (specDescs != null)
            {
                uint specDataSize = 0;
                foreach (SpecializationConstant spec in specDescs)
                {
                    specDataSize += VkFormats.GetSpecializationConstantSize(spec.Type);
                }
                byte *fullSpecData                   = stackalloc byte[(int)specDataSize];
                int   specializationCount            = specDescs.Length;
                VkSpecializationMapEntry *mapEntries = stackalloc VkSpecializationMapEntry[specializationCount];
                uint specOffset = 0;
                for (int i = 0; i < specializationCount; i++)
                {
                    ulong data     = specDescs[i].Data;
                    byte *srcData  = (byte *)&data;
                    uint  dataSize = VkFormats.GetSpecializationConstantSize(specDescs[i].Type);
                    Unsafe.CopyBlock(fullSpecData + specOffset, srcData, dataSize);
                    mapEntries[i].constantID = specDescs[i].ID;
                    mapEntries[i].offset     = specOffset;
                    mapEntries[i].size       = (UIntPtr)dataSize;
                    specOffset += dataSize;
                }
                specializationInfo.dataSize      = (UIntPtr)specDataSize;
                specializationInfo.pData         = fullSpecData;
                specializationInfo.mapEntryCount = (uint)specializationCount;
                specializationInfo.pMapEntries   = mapEntries;
            }

            Shader   shader   = description.ComputeShader;
            VkShader vkShader = Util.AssertSubtype <Shader, VkShader>(shader);
            VkPipelineShaderStageCreateInfo stageCI = VkPipelineShaderStageCreateInfo.New();

            stageCI.module = vkShader.ShaderModule;
            stageCI.stage  = VkFormats.VdToVkShaderStages(shader.Stage);
            stageCI.pName  = CommonStrings.main; // Meh
            stageCI.pSpecializationInfo = &specializationInfo;
            pipelineCI.stage            = stageCI;

            VkResult result = vkCreateComputePipelines(
                _gd.Device,
                VkPipelineCache.Null,
                1,
                ref pipelineCI,
                null,
                out _devicePipeline);

            CheckResult(result);

            ResourceSetCount    = (uint)description.ResourceLayouts.Length;
            DynamicOffsetsCount = 0;
            foreach (VkResourceLayout layout in description.ResourceLayouts)
            {
                DynamicOffsetsCount += layout.DynamicBufferCount;
            }
        }
Beispiel #14
0
        protected override async void InternalLoad()
        {
            var swapChainDescription = this.swapChain?.SwapChainDescription;

            this.width  = swapChainDescription.Value.Width;
            this.height = swapChainDescription.Value.Height;

            // Create Scene
            BasicScene();

            // Compute Resources
            var spheresBufferDescription = new BufferDescription(
                (uint)(Unsafe.SizeOf <Sphere>() * spheres.Length),
                BufferFlags.UnorderedAccess | BufferFlags.ShaderResource | BufferFlags.BufferStructured,
                ResourceUsage.Default,
                ResourceCpuAccess.None,
                Unsafe.SizeOf <Sphere>());

            spheresBuffer = this.graphicsContext.Factory.CreateBuffer(spheres, ref spheresBufferDescription);

            var materialsBufferDescription = new BufferDescription(
                (uint)(Unsafe.SizeOf <Material>() * spheres.Length),
                BufferFlags.UnorderedAccess | BufferFlags.ShaderResource | BufferFlags.BufferStructured,
                ResourceUsage.Default,
                ResourceCpuAccess.None,
                Unsafe.SizeOf <Material>());

            materialsBuffer = this.graphicsContext.Factory.CreateBuffer(materials, ref materialsBufferDescription);

            this.threadGroupX = this.width / 16u;
            this.threadGroupY = this.height / 16u;

            CompilerParameters parameters = new CompilerParameters()
            {
                CompilationMode = CompilationMode.None,
                Profile         = GraphicsProfile.Level_11_0,
            };

            var computeShaderDescription = await this.assetsDirectory.ReadAndCompileShader(this.graphicsContext, "CS", "ComputeShader", ShaderStages.Compute, "CS", parameters);

            var computeShader = this.graphicsContext.Factory.CreateShader(ref computeShaderDescription);

            var textureDescription = new TextureDescription()
            {
                Type        = TextureType.Texture2D,
                Usage       = ResourceUsage.Default,
                Flags       = TextureFlags.UnorderedAccess | TextureFlags.ShaderResource,
                Format      = PixelFormat.R8G8B8A8_UNorm,
                Width       = this.width,
                Height      = this.height,
                Depth       = 1,
                MipLevels   = 1,
                ArraySize   = 1,
                CpuAccess   = ResourceCpuAccess.None,
                SampleCount = TextureSampleCount.None,
            };

            Texture texture2D = this.graphicsContext.Factory.CreateTexture(ref textureDescription);

            this.computeData = new ComputeData()
            {
                time        = 0,
                width       = this.width,
                height      = this.height,
                framecount  = 0,
                samples     = 25,
                recursion   = 5,
                spherecount = (uint)spheres.Length,
                cam         = this.cam
            };

            var constantBufferDescription = new BufferDescription((uint)Unsafe.SizeOf <ComputeData>(), BufferFlags.ConstantBuffer, ResourceUsage.Default);

            this.constantBuffer = this.graphicsContext.Factory.CreateBuffer(ref this.computeData, ref constantBufferDescription);

            ResourceLayoutDescription computeLayoutDescription = new ResourceLayoutDescription(
                new LayoutElementDescription(0, ResourceType.StructuredBuffer, ShaderStages.Compute),
                new LayoutElementDescription(1, ResourceType.StructuredBuffer, ShaderStages.Compute),
                new LayoutElementDescription(0, ResourceType.ConstantBuffer, ShaderStages.Compute),
                new LayoutElementDescription(0, ResourceType.TextureReadWrite, ShaderStages.Compute));

            ResourceLayout computeResourceLayout = this.graphicsContext.Factory.CreateResourceLayout(ref computeLayoutDescription);

            ResourceSetDescription computeResourceSetDescription = new ResourceSetDescription(computeResourceLayout, this.spheresBuffer, this.materialsBuffer, this.constantBuffer, texture2D);

            this.computeResourceSet = this.graphicsContext.Factory.CreateResourceSet(ref computeResourceSetDescription);

            var computePipelineDescription = new ComputePipelineDescription()
            {
                ComputeShader    = computeShader,
                ResourceLayouts  = new[] { computeResourceLayout },
                ThreadGroupSizeX = 16,
                ThreadGroupSizeY = 16,
                ThreadGroupSizeZ = 1,
            };

            this.computePipelineState = this.graphicsContext.Factory.CreateComputePipeline(ref computePipelineDescription);

            // Graphics Resources
            var vertexShaderDescription = await this.assetsDirectory.ReadAndCompileShader(this.graphicsContext, "HLSL", "VertexShader", ShaderStages.Vertex, "VS");

            var pixelShaderDescription = await this.assetsDirectory.ReadAndCompileShader(this.graphicsContext, "HLSL", "FragmentShader", ShaderStages.Pixel, "PS");

            var vertexShader = this.graphicsContext.Factory.CreateShader(ref vertexShaderDescription);
            var pixelShader  = this.graphicsContext.Factory.CreateShader(ref pixelShaderDescription);

            var samplerDescription = SamplerStates.LinearClamp;
            var samplerState       = this.graphicsContext.Factory.CreateSamplerState(ref samplerDescription);

            // Set Params
            this.paramsData.Samples       = 1;
            this.paramsData.IsPathTracing = false;

            var paramsBufferDescription = new BufferDescription((uint)Unsafe.SizeOf <Params>(), BufferFlags.ConstantBuffer, ResourceUsage.Default);

            this.paramsBuffer = this.graphicsContext.Factory.CreateBuffer(ref paramsBufferDescription);

            ResourceLayoutDescription layoutDescription = new ResourceLayoutDescription(
                new LayoutElementDescription(0, ResourceType.ConstantBuffer, ShaderStages.Pixel),
                new LayoutElementDescription(0, ResourceType.Texture, ShaderStages.Pixel),
                new LayoutElementDescription(0, ResourceType.Sampler, ShaderStages.Pixel));
            ResourceLayout resourceLayout = this.graphicsContext.Factory.CreateResourceLayout(ref layoutDescription);

            ResourceSetDescription resourceSetDescription = new ResourceSetDescription(resourceLayout, this.paramsBuffer, texture2D, samplerState);

            this.resourceSet = this.graphicsContext.Factory.CreateResourceSet(ref resourceSetDescription);

            BlendStateDescription blend = BlendStateDescription.Default;

            if (this.paramsData.IsPathTracing)
            {
                blend.RenderTarget0.BlendEnable           = true;
                blend.RenderTarget0.SourceBlendColor      = Blend.SourceAlpha;
                blend.RenderTarget0.DestinationBlendColor = Blend.InverseSourceAlpha;
            }
            else
            {
                blend = BlendStates.Opaque;
            }

            var pipelineDescription = new GraphicsPipelineDescription()
            {
                PrimitiveTopology = PrimitiveTopology.TriangleList,
                InputLayouts      = null,
                ResourceLayouts   = new[] { resourceLayout },
                Shaders           = new ShaderStateDescription()
                {
                    VertexShader = vertexShader,
                    PixelShader  = pixelShader,
                },
                RenderStates = new RenderStateDescription()
                {
                    RasterizerState   = RasterizerStates.CullBack,
                    BlendState        = blend,
                    DepthStencilState = DepthStencilStates.Read,
                },
                Outputs = this.frameBuffer.OutputDescription,
            };

            this.graphicsPipelineState = this.graphicsContext.Factory.CreateGraphicsPipeline(ref pipelineDescription);
            this.graphicsCommandQueue  = this.graphicsContext.Factory.CreateCommandQueue(CommandQueueType.Graphics);
            this.computeCommandQueue   = this.graphicsContext.Factory.CreateCommandQueue(CommandQueueType.Compute);

            this.viewports    = new Viewport[1];
            this.viewports[0] = new Viewport(0, 0, this.width, this.height);
            this.scissors     = new Rectangle[1];
            this.scissors[0]  = new Rectangle(0, 0, (int)this.width, (int)this.height);
        }
Beispiel #15
0
 /// <summary>
 /// Creates a new compute <see cref="Pipeline"/> object.
 /// </summary>
 /// <param name="description">The desirede properties of the created object.</param>
 /// <returns>A new <see cref="Pipeline"/> which, when bound to a CommandList, is used to dispatch compute commands.</returns>
 public abstract Pipeline CreateComputePipeline(ref ComputePipelineDescription description);
Beispiel #16
0
 /// <summary>
 /// Creates a new compute <see cref="Pipeline"/> object.
 /// </summary>
 /// <param name="description">The desirede properties of the created object.</param>
 /// <returns>A new <see cref="Pipeline"/> which, when bound to a CommandList, is used to dispatch compute commands.</returns>
 public Pipeline CreateComputePipeline(ComputePipelineDescription description) => CreateComputePipeline(ref description);
Beispiel #17
0
        protected override void CreateResources(ResourceFactory factory)
        {
            _screenSizeBuffer = factory.CreateBuffer(new BufferDescription(16, BufferUsage.UniformBuffer));
            _shiftBuffer      = factory.CreateBuffer(new BufferDescription(16, BufferUsage.UniformBuffer));
            _vertexBuffer     = factory.CreateBuffer(new BufferDescription(16 * 4, BufferUsage.VertexBuffer));
            _indexBuffer      = factory.CreateBuffer(new BufferDescription(2 * 6, BufferUsage.IndexBuffer));

            _computeShader = factory.CreateShader(new ShaderDescription(
                                                      ShaderStages.Compute,
                                                      File.ReadAllBytes(Path.Combine(AppContext.BaseDirectory, "Shaders", $"Compute.{GetExtension(factory.BackendType)}")),
                                                      "CS"));

            _computeLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
                                                              new ResourceLayoutElementDescription("Tex", ResourceKind.TextureReadWrite, ShaderStages.Compute),
                                                              new ResourceLayoutElementDescription("ScreenSizeBuffer", ResourceKind.UniformBuffer, ShaderStages.Compute),
                                                              new ResourceLayoutElementDescription("ShiftBuffer", ResourceKind.UniformBuffer, ShaderStages.Compute)));

            ComputePipelineDescription computePipelineDesc = new ComputePipelineDescription(
                _computeShader,
                _computeLayout,
                1, 1, 1);

            _computePipeline = factory.CreateComputePipeline(ref computePipelineDesc);

            _vertexShader = factory.CreateShader(new ShaderDescription(
                                                     ShaderStages.Vertex,
                                                     File.ReadAllBytes(Path.Combine(AppContext.BaseDirectory, "Shaders", $"Vertex.{GetExtension(factory.BackendType)}")),
                                                     "VS"));
            _fragmentShader = factory.CreateShader(new ShaderDescription(
                                                       ShaderStages.Fragment,
                                                       File.ReadAllBytes(Path.Combine(AppContext.BaseDirectory, "Shaders", $"Fragment.{GetExtension(factory.BackendType)}")),
                                                       "FS"));

            ShaderSetDescription shaderSet = new ShaderSetDescription(
                new VertexLayoutDescription[]
            {
                new VertexLayoutDescription(
                    new VertexElementDescription("Position", VertexElementSemantic.Position, VertexElementFormat.Float2),
                    new VertexElementDescription("TexCoord", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2))
            },
                new[]
            {
                _vertexShader,
                _fragmentShader
            });

            _graphicsLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
                                                               new ResourceLayoutElementDescription("Tex", ResourceKind.TextureReadOnly, ShaderStages.Fragment),
                                                               new ResourceLayoutElementDescription("Tex11", ResourceKind.TextureReadOnly, ShaderStages.Fragment),
                                                               new ResourceLayoutElementDescription("Tex22", ResourceKind.TextureReadOnly, ShaderStages.Fragment),
                                                               new ResourceLayoutElementDescription("SS", ResourceKind.Sampler, ShaderStages.Fragment)));

            GraphicsPipelineDescription fullScreenQuadDesc = new GraphicsPipelineDescription(
                BlendStateDescription.SingleOverrideBlend,
                DepthStencilStateDescription.Disabled,
                new RasterizerStateDescription(FaceCullMode.Back, PolygonFillMode.Solid, FrontFace.Clockwise, false, false),
                PrimitiveTopology.TriangleList,
                shaderSet,
                new[] { _graphicsLayout },
                _gd.SwapchainFramebuffer.OutputDescription);

            _graphicsPipeline = factory.CreateGraphicsPipeline(ref fullScreenQuadDesc);

            _cl = factory.CreateCommandList();

            CreateWindowSizedResources(factory);
            InitResources(factory);
        }
Beispiel #18
0
 public override Pipeline CreateComputePipeline(ref ComputePipelineDescription description)
 {
     return(new MTLPipeline(ref description, _gd));
 }
        protected override void CreateResources(ResourceFactory factory)
        {
            _particleBuffer = factory.CreateBuffer(
                new BufferDescription(
                    (uint)Unsafe.SizeOf <ParticleInfo>() * ParticleCount,
                    BufferUsage.StructuredBufferReadWrite,
                    (uint)Unsafe.SizeOf <ParticleInfo>()));

            _screenSizeBuffer = factory.CreateBuffer(new BufferDescription(16, BufferUsage.UniformBuffer));

            _computeShader = factory.CreateFromSpirv(new ShaderDescription(
                                                         ShaderStages.Compute,
                                                         ReadEmbeddedAssetBytes($"Compute.glsl"),
                                                         "main"));

            ResourceLayout particleStorageLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
                                                                                    new ResourceLayoutElementDescription("ParticlesBuffer", ResourceKind.StructuredBufferReadWrite, ShaderStages.Compute)));

            ResourceLayout screenSizeLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
                                                                               new ResourceLayoutElementDescription("ScreenSizeBuffer", ResourceKind.UniformBuffer, ShaderStages.Compute)));

            ComputePipelineDescription computePipelineDesc = new ComputePipelineDescription(
                _computeShader,
                new[] { particleStorageLayout, screenSizeLayout },
                1, 1, 1);

            _computePipeline = factory.CreateComputePipeline(ref computePipelineDesc);

            _computeResourceSet = factory.CreateResourceSet(new ResourceSetDescription(particleStorageLayout, _particleBuffer));

            _computeScreenSizeResourceSet = factory.CreateResourceSet(new ResourceSetDescription(screenSizeLayout, _screenSizeBuffer));

            var result = SpirvCompilation.CompileVertexFragment(ReadEmbeddedAssetBytes($"Vertex.glsl"), ReadEmbeddedAssetBytes($"Fragment.glsl"), CrossCompileTarget.MSL);

            var shaders = factory.CreateFromSpirv(
                new ShaderDescription(
                    ShaderStages.Vertex,
                    ReadEmbeddedAssetBytes($"Vertex.glsl"),
                    "main"),
                new ShaderDescription(
                    ShaderStages.Fragment,
                    ReadEmbeddedAssetBytes($"Fragment.glsl"),
                    "main"));

            ShaderSetDescription shaderSet = new ShaderSetDescription(
                Array.Empty <VertexLayoutDescription>(),
                shaders);

            particleStorageLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
                                                                     new ResourceLayoutElementDescription("ParticlesBuffer", ResourceKind.StructuredBufferReadOnly, ShaderStages.Vertex)));

            screenSizeLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
                                                                new ResourceLayoutElementDescription("ScreenSizeBuffer", ResourceKind.UniformBuffer, ShaderStages.Vertex)));

            GraphicsPipelineDescription particleDrawPipelineDesc = new GraphicsPipelineDescription(
                BlendStateDescription.SingleOverrideBlend,
                new DepthStencilStateDescription(true, true, ComparisonKind.Always),
                RasterizerStateDescription.Default,
                PrimitiveTopology.PointList,
                shaderSet,
                new[] { particleStorageLayout, screenSizeLayout },
                MainSwapchain.Framebuffer.OutputDescription);;

            _graphicsPipeline = factory.CreateGraphicsPipeline(ref particleDrawPipelineDesc);

            _graphicsParticleResourceSet = factory.CreateResourceSet(new ResourceSetDescription(
                                                                         particleStorageLayout,
                                                                         _particleBuffer));

            _screenSizeResourceSet = factory.CreateResourceSet(new ResourceSetDescription(
                                                                   screenSizeLayout,
                                                                   _screenSizeBuffer));

            _cl = factory.CreateCommandList();

            InitResources(factory);
            _initialized = true;
        }
        protected override void CreateResources(ResourceFactory factory)
        {
            _particleBuffer = factory.CreateBuffer(
                new BufferDescription(
                    (uint)Unsafe.SizeOf <ParticleInfo>() * ParticleCount,
                    BufferUsage.StructuredBufferReadWrite,
                    (uint)Unsafe.SizeOf <ParticleInfo>()));

            _screenSizeBuffer = factory.CreateBuffer(new BufferDescription(16, BufferUsage.UniformBuffer));

            _computeShader = factory.CreateShader(new ShaderDescription(
                                                      ShaderStages.Compute,
                                                      ReadEmbeddedAssetBytes($"Compute.{GetExtension(factory.BackendType)}"),
                                                      "CS"));

            ResourceLayout particleStorageLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
                                                                                    new ResourceLayoutElementDescription("ParticlesBuffer", ResourceKind.StructuredBufferReadWrite, ShaderStages.Compute)));

            ResourceLayout screenSizeLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
                                                                               new ResourceLayoutElementDescription("ScreenSizeBuffer", ResourceKind.UniformBuffer, ShaderStages.Compute)));

            ComputePipelineDescription computePipelineDesc = new ComputePipelineDescription(
                _computeShader,
                new[] { particleStorageLayout, screenSizeLayout },
                1, 1, 1);

            _computePipeline = factory.CreateComputePipeline(ref computePipelineDesc);

            _computeResourceSet = factory.CreateResourceSet(new ResourceSetDescription(particleStorageLayout, _particleBuffer));

            _computeScreenSizeResourceSet = factory.CreateResourceSet(new ResourceSetDescription(screenSizeLayout, _screenSizeBuffer));

            _vertexShader = factory.CreateShader(new ShaderDescription(
                                                     ShaderStages.Vertex,
                                                     ReadEmbeddedAssetBytes($"Vertex.{GetExtension(factory.BackendType)}"),
                                                     "VS"));
            _fragmentShader = factory.CreateShader(new ShaderDescription(
                                                       ShaderStages.Fragment,
                                                       ReadEmbeddedAssetBytes($"Fragment.{GetExtension(factory.BackendType)}"),
                                                       "FS"));

            ShaderSetDescription shaderSet = new ShaderSetDescription(
                Array.Empty <VertexLayoutDescription>(),
                new[]
            {
                _vertexShader,
                _fragmentShader
            });

            particleStorageLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
                                                                     new ResourceLayoutElementDescription("ParticlesBuffer", ResourceKind.StructuredBufferReadOnly, ShaderStages.Vertex)));

            screenSizeLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
                                                                new ResourceLayoutElementDescription("ScreenSizeBuffer", ResourceKind.UniformBuffer, ShaderStages.Vertex)));

            GraphicsPipelineDescription particleDrawPipelineDesc = new GraphicsPipelineDescription(
                BlendStateDescription.SingleOverrideBlend,
                DepthStencilStateDescription.Disabled,
                RasterizerStateDescription.Default,
                PrimitiveTopology.PointList,
                shaderSet,
                new[] { particleStorageLayout, screenSizeLayout },
                MainSwapchain.Framebuffer.OutputDescription);

            _graphicsPipeline = factory.CreateGraphicsPipeline(ref particleDrawPipelineDesc);

            _graphicsParticleResourceSet = factory.CreateResourceSet(new ResourceSetDescription(
                                                                         particleStorageLayout,
                                                                         _particleBuffer));

            _screenSizeResourceSet = factory.CreateResourceSet(new ResourceSetDescription(
                                                                   screenSizeLayout,
                                                                   _screenSizeBuffer));

            _cl = factory.CreateCommandList();

            InitResources(factory);
            _initialized = true;
        }
 public override Pipeline CreateComputePipeline(ref ComputePipelineDescription description)
 => Track(_factory.CreateComputePipeline(description));
Beispiel #22
0
        protected override void CreateResources(ResourceFactory factory)
        {
            _screenSizeBuffer = factory.CreateBuffer(new BufferDescription(16, BufferUsage.UniformBuffer));
            _shiftBuffer      = factory.CreateBuffer(new BufferDescription(16, BufferUsage.UniformBuffer));
            _vertexBuffer     = factory.CreateBuffer(new BufferDescription(16 * 4, BufferUsage.VertexBuffer));
            _indexBuffer      = factory.CreateBuffer(new BufferDescription(2 * 6, BufferUsage.IndexBuffer));

            _computeShader = factory.CreateFromSpirv(new ShaderDescription(
                                                         ShaderStages.Compute,
                                                         ReadEmbeddedAssetBytes("Compute.glsl"),
                                                         "main"));

            _computeLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
                                                              new ResourceLayoutElementDescription("Tex", ResourceKind.TextureReadWrite, ShaderStages.Compute),
                                                              new ResourceLayoutElementDescription("ScreenSizeBuffer", ResourceKind.UniformBuffer, ShaderStages.Compute),
                                                              new ResourceLayoutElementDescription("ShiftBuffer", ResourceKind.UniformBuffer, ShaderStages.Compute)));

            ComputePipelineDescription computePipelineDesc = new ComputePipelineDescription(
                _computeShader,
                _computeLayout,
                16, 16, 1);

            _computePipeline = factory.CreateComputePipeline(ref computePipelineDesc);

            Shader[] shaders = factory.CreateFromSpirv(
                new ShaderDescription(
                    ShaderStages.Vertex,
                    ReadEmbeddedAssetBytes("Vertex.glsl"),
                    "main"),
                new ShaderDescription(
                    ShaderStages.Fragment,
                    ReadEmbeddedAssetBytes("Fragment.glsl"),
                    "main"));

            ShaderSetDescription shaderSet = new ShaderSetDescription(
                new VertexLayoutDescription[]
            {
                new VertexLayoutDescription(
                    new VertexElementDescription("Position", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2),
                    new VertexElementDescription("TexCoord", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2))
            },
                shaders);

            _graphicsLayout = factory.CreateResourceLayout(new ResourceLayoutDescription(
                                                               new ResourceLayoutElementDescription("Tex", ResourceKind.TextureReadOnly, ShaderStages.Fragment),
                                                               new ResourceLayoutElementDescription("Tex11", ResourceKind.TextureReadOnly, ShaderStages.Fragment),
                                                               new ResourceLayoutElementDescription("Tex22", ResourceKind.TextureReadOnly, ShaderStages.Fragment),
                                                               new ResourceLayoutElementDescription("SS", ResourceKind.Sampler, ShaderStages.Fragment)));

            GraphicsPipelineDescription fullScreenQuadDesc = new GraphicsPipelineDescription(
                BlendStateDescription.SingleOverrideBlend,
                DepthStencilStateDescription.Disabled,
                new RasterizerStateDescription(FaceCullMode.Back, PolygonFillMode.Solid, FrontFace.Clockwise, true, false),
                PrimitiveTopology.TriangleList,
                shaderSet,
                new[] { _graphicsLayout },
                MainSwapchain.Framebuffer.OutputDescription);

            _graphicsPipeline = factory.CreateGraphicsPipeline(ref fullScreenQuadDesc);

            _cl = factory.CreateCommandList();

            CreateWindowSizedResources(factory);
            InitResources(factory);
        }
Beispiel #23
0
 public override Pipeline CreateComputePipeline(ref ComputePipelineDescription description)
 {
     return(new OpenGLPipeline(_gd, ref description));
 }
 public override Pipeline CreateComputePipeline(ref ComputePipelineDescription description)
 {
     return(new D3D11Pipeline(_cache, ref description));
 }
Beispiel #25
0
        public MTLPipeline(ref ComputePipelineDescription description, MTLGraphicsDevice gd)
            : base(ref description)
        {
            IsComputePipeline = true;
            ResourceLayouts   = new MTLResourceLayout[description.ResourceLayouts.Length];
            for (int i = 0; i < ResourceLayouts.Length; i++)
            {
                ResourceLayouts[i] = Util.AssertSubtype <ResourceLayout, MTLResourceLayout>(description.ResourceLayouts[i]);
            }

            ThreadsPerThreadgroup = new MTLSize(
                description.ThreadGroupSizeX,
                description.ThreadGroupSizeY,
                description.ThreadGroupSizeZ);

            MTLComputePipelineDescriptor mtlDesc = MTLUtil.AllocInit <MTLComputePipelineDescriptor>(
                nameof(MTLComputePipelineDescriptor));
            MTLShader   mtlShader = Util.AssertSubtype <Shader, MTLShader>(description.ComputeShader);
            MTLFunction specializedFunction;

            if (mtlShader.HasFunctionConstants)
            {
                // Need to create specialized MTLFunction.
                MTLFunctionConstantValues constantValues = CreateConstantValues(description.Specializations);
                specializedFunction = mtlShader.Library.newFunctionWithNameConstantValues(mtlShader.EntryPoint, constantValues);
                AddSpecializedFunction(specializedFunction);
                ObjectiveCRuntime.release(constantValues.NativePtr);

                Debug.Assert(specializedFunction.NativePtr != IntPtr.Zero, "Failed to create specialized MTLFunction");
            }
            else
            {
                specializedFunction = mtlShader.Function;
            }

            mtlDesc.computeFunction = specializedFunction;
            MTLPipelineBufferDescriptorArray buffers = mtlDesc.buffers;
            uint bufferIndex = 0;

            foreach (MTLResourceLayout layout in ResourceLayouts)
            {
                foreach (ResourceKind kind in layout.ResourceKinds)
                {
                    if (kind == ResourceKind.UniformBuffer ||
                        kind == ResourceKind.StructuredBufferReadOnly)
                    {
                        MTLPipelineBufferDescriptor bufferDesc = buffers[bufferIndex];
                        bufferDesc.mutability = MTLMutability.Immutable;
                        bufferIndex          += 1;
                    }
                    else if (kind == ResourceKind.StructuredBufferReadWrite)
                    {
                        MTLPipelineBufferDescriptor bufferDesc = buffers[bufferIndex];
                        bufferDesc.mutability = MTLMutability.Mutable;
                        bufferIndex          += 1;
                    }
                }
            }

            ComputePipelineState = gd.Device.newComputePipelineStateWithDescriptor(mtlDesc);

            ObjectiveCRuntime.release(mtlDesc.NativePtr);
        }