Пример #1
0
        private VertexLayoutDescription createVertexLayout()
        {
            var vertexElementDescriptionPosition = new VertexElementDescription("Position", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2);
            var vertexElementDescriptionColor    = new VertexElementDescription("Color", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float4);

            return(new VertexLayoutDescription(vertexElementDescriptionPosition, vertexElementDescriptionColor));
        }
Пример #2
0
 public IPipelineBuilder With(VertexElementDescription vertexElementDescr)
 {
     if (Collection.Factory.BackendType == GraphicsBackend.Direct3D11)
     {
         vertexElementDescr.Semantic = VertexElementSemantic.TextureCoordinate; // TODO: Maybe watch the Veldrid bug for that?
     }
     vertexElements.Last().Add(vertexElementDescr);
     return(this);
 }
Пример #3
0
        public override VertexElementDescription[] GetVertexElementDescriptions()
        {
            // Ignore last VertexElement, because it's D3DDECLEND
            var result = new VertexElementDescription[VertexElements.Length - 1];

            for (var i = 0; i < result.Length; i++)
            {
                result[i] = VertexElements[i].GetVertexElementDescription();
            }
            return(result);
        }
Пример #4
0
        /*
         *
         * Display icons for the visualiser bar
         *
         */

        public static ShaderSetDescription CreateVisBarPointIconShader(GraphicsDevice gd)
        {
            VertexElementDescription VEDpos       = new VertexElementDescription("Coord", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2);
            VertexElementDescription VEDcol       = new VertexElementDescription("Color", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float4);
            VertexLayoutDescription  vertexLayout = new VertexLayoutDescription(VEDpos, VEDcol);

            byte[]            nodeVertShaderBytes = Encoding.UTF8.GetBytes(Shaders.SPIR_V.SPIRVShaders.vs_visbar_points);
            byte[]            nodeFragShaderBytes = Encoding.UTF8.GetBytes(Shaders.SPIR_V.SPIRVShaders.fs_visbar_points);
            ShaderDescription vertexShaderDesc    = new ShaderDescription(ShaderStages.Vertex, nodeVertShaderBytes, "main");
            ShaderDescription fragmentShaderDesc  = new ShaderDescription(ShaderStages.Fragment, nodeFragShaderBytes, "main");

            ShaderSetDescription shaderSetDesc = new ShaderSetDescription(
                vertexLayouts: new VertexLayoutDescription[] { vertexLayout },
                shaders: gd.ResourceFactory.CreateFromSpirv(vertexShaderDesc, fragmentShaderDesc));

            return(shaderSetDesc);
        }
Пример #5
0
        /*
         *
         * Picking node points for mousing over instruction verts
         *
         */


        public static ShaderSetDescription CreateNodePickingShaders(GraphicsDevice gd, out DeviceBuffer vertBuffer)
        {
            VertexElementDescription VEDpos       = new VertexElementDescription("PositionBufIndex", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Int1);
            VertexElementDescription VEDcol       = new VertexElementDescription("Color", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float4);
            VertexLayoutDescription  vertexLayout = new VertexLayoutDescription(VEDpos, VEDcol);

            byte[]            vertShaderBytes    = Encoding.UTF8.GetBytes(Shaders.SPIR_V.SPIRVShaders.vspickingglsl);
            byte[]            fragShaderBytes    = Encoding.UTF8.GetBytes(Shaders.SPIR_V.SPIRVShaders.fspickingglsl);
            ShaderDescription vertexShaderDesc   = new ShaderDescription(ShaderStages.Vertex, vertShaderBytes, "main");
            ShaderDescription fragmentShaderDesc = new ShaderDescription(ShaderStages.Fragment, fragShaderBytes, "main");

            ShaderSetDescription shaderSetDesc = new ShaderSetDescription(
                vertexLayouts: new VertexLayoutDescription[] { vertexLayout },
                shaders: gd.ResourceFactory.CreateFromSpirv(vertexShaderDesc, fragmentShaderDesc));

            vertBuffer = VeldridGraphBuffers.TrackedVRAMAlloc(gd, 1, BufferUsage.VertexBuffer, name: "NodePickingShaderVertexBufInitial");
            return(shaderSetDesc);
        }
Пример #6
0
        public override VertexElementDescription[] GetVertexElementDescriptions()
        {
            // For example:
            // p0:00:3f32 n0:0C:3f32 c0:18:4u8n g0:1C:3f32 b0:28:3f32 t0:34:2f32

            var elements = VertexDeclaration.Split(' ');
            var result   = new VertexElementDescription[elements.Length];

            for (var i = 0; i < result.Length; i++)
            {
                var parts = elements[i].Split(':');
                result[i] = new VertexElementDescription(
                    parts[0],
                    VertexElementSemantic.TextureCoordinate,
                    GetFormat(parts[2]),
                    Convert.ToUInt32(parts[1], 16));
            }
            return(result);
        }
Пример #7
0
        private void FlushVertexLayouts()
        {
            uint totalSlotsBound = 0;

            VertexLayoutDescription[] layouts = _graphicsPipeline.GraphicsDescription.ShaderSet.VertexLayouts;
            for (int i = 0; i < layouts.Length; i++)
            {
                VertexLayoutDescription input = layouts[i];
                OpenGLBuffer            vb    = _vertexBuffers[i];
                glBindBuffer(BufferTarget.ArrayBuffer, vb.Buffer);
                uint offset = 0;
                for (uint slot = 0; slot < input.Elements.Length; slot++)
                {
                    ref VertexElementDescription element = ref input.Elements[slot]; // Large structure -- use by reference.
                    uint actualSlot = totalSlotsBound + slot;
                    if (actualSlot >= _vertexAttributesBound)
                    {
                        glEnableVertexAttribArray(actualSlot);
                    }
                    VertexAttribPointerType type = OpenGLFormats.VdToGLVertexAttribPointerType(
                        element.Format,
                        out bool normalized);
                    glVertexAttribPointer(
                        actualSlot,
                        FormatHelpers.GetElementCount(element.Format),
                        type,
                        normalized,
                        (uint)_graphicsPipeline.VertexStrides[i],
                        (void *)offset);

                    uint stepRate = input.InstanceStepRate;
                    if (_vertexAttribDivisors[actualSlot] != stepRate)
                    {
                        glVertexAttribDivisor(actualSlot, stepRate);
                        _vertexAttribDivisors[actualSlot] = stepRate;
                    }

                    offset += FormatHelpers.GetSizeInBytes(element.Format);
                }

                totalSlotsBound += (uint)input.Elements.Length;
            }
Пример #8
0
        /*
         *
         * Font triangles
         *
         */
        public static ShaderSetDescription CreateFontShaders(GraphicsDevice gd, out DeviceBuffer vertBuffer)
        {
            VertexElementDescription nodeIdx = new VertexElementDescription("nodeIdx", VertexElementSemantic.TextureCoordinate, VertexElementFormat.UInt1);
            VertexElementDescription VEDpos  = new VertexElementDescription("Position", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float3);
            VertexElementDescription Charpos = new VertexElementDescription("CharCoord", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float2);
            VertexElementDescription yoff    = new VertexElementDescription("YOffset", VertexElementSemantic.TextureCoordinate, VertexElementFormat.Float1);
            VertexElementDescription fcol    = new VertexElementDescription("FontColour", VertexElementSemantic.Color, VertexElementFormat.Float4);

            VertexLayoutDescription vertexLayout = new VertexLayoutDescription(nodeIdx, VEDpos, Charpos, yoff, fcol);

            byte[]            vertShaderBytes    = Encoding.UTF8.GetBytes(Shaders.SPIR_V.SPIRVShaders.vsfontglsl);
            byte[]            fragShaderBytes    = Encoding.UTF8.GetBytes(Shaders.SPIR_V.SPIRVShaders.fsfontglsl);
            ShaderDescription vertexShaderDesc   = new ShaderDescription(ShaderStages.Vertex, vertShaderBytes, "main");
            ShaderDescription fragmentShaderDesc = new ShaderDescription(ShaderStages.Fragment, fragShaderBytes, "main");

            ShaderSetDescription shaderSetDesc = new ShaderSetDescription(
                vertexLayouts: new VertexLayoutDescription[] { vertexLayout },
                shaders: gd.ResourceFactory.CreateFromSpirv(vertexShaderDesc, fragmentShaderDesc));

            vertBuffer = VeldridGraphBuffers.TrackedVRAMAlloc(gd, 1, BufferUsage.VertexBuffer, name: "FontShaderVertexBufInitial");
            return(shaderSetDesc);
        }
Пример #9
0
        private InputLayout CreateNewInputLayout(VertexLayoutDescription[] vertexLayouts, byte[] vsBytecode)
        {
            int totalCount = 0;

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

            int element = 0; // Total element index across slots.

            InputElement[]  elements = new InputElement[totalCount];
            SemanticIndices si       = new SemanticIndices();

            for (int slot = 0; slot < vertexLayouts.Length; slot++)
            {
                VertexElementDescription[] elementDescs = vertexLayouts[slot].Elements;
                uint stepRate      = vertexLayouts[slot].InstanceStepRate;
                int  currentOffset = 0;
                for (int i = 0; i < elementDescs.Length; i++)
                {
                    VertexElementDescription desc = elementDescs[i];
                    elements[element] = new InputElement(
                        GetSemanticString(desc.Semantic),
                        SemanticIndices.GetAndIncrement(ref si, desc.Semantic),
                        D3D11Formats.ToDxgiFormat(desc.Format),
                        currentOffset,
                        slot,
                        stepRate == 0 ? InputClassification.PerVertexData : InputClassification.PerInstanceData,
                        (int)stepRate);

                    currentOffset += (int)FormatHelpers.GetSizeInBytes(desc.Format);
                    element       += 1;
                }
            }

            return(new InputLayout(_device, vsBytecode, elements));
        }
Пример #10
0
        override protected void CreateResources()
        {
            _cameraProjViewBuffer = _factory.CreateBuffer(new BufferDescription(128, BufferUsage.UniformBuffer | BufferUsage.Dynamic));

            ResourceLayoutElementDescription resourceLayoutElementDescription = new ResourceLayoutElementDescription("projView", ResourceKind.UniformBuffer, ShaderStages.Vertex);

            ResourceLayoutElementDescription[] resourceLayoutElementDescriptions = { resourceLayoutElementDescription };
            ResourceLayoutDescription          resourceLayoutDescription         = new ResourceLayoutDescription(resourceLayoutElementDescriptions);

            BindableResource[] bindableResources = new BindableResource[] { _cameraProjViewBuffer };

            _resourceLayout = _factory.CreateResourceLayout(resourceLayoutDescription);
            ResourceSetDescription resourceSetDescription = new ResourceSetDescription(_resourceLayout, bindableResources);

            _resourceSet = _factory.CreateResourceSet(resourceSetDescription);

            Mesh <VertexPositionNDCColor> coloredQuad
                = GeometryFactory.GenerateColorQuadNDC_XY(RgbaFloat.Red, RgbaFloat.Green, RgbaFloat.Blue, RgbaFloat.Yellow);

            ushort[] quadIndicies = GeometryFactory.GenerateQuadIndicies_TriangleStrip_CW();

            float[] _xOffset = { -2f, 2f };

            // declare (VBO) buffers
            _vertexBuffer
                = _factory.CreateBuffer(new BufferDescription(coloredQuad.Vertices.LengthUnsigned() * VertexPositionNDCColor.SizeInBytes, BufferUsage.VertexBuffer));
            _indexBuffer
                = _factory.CreateBuffer(new BufferDescription(quadIndicies.LengthUnsigned() * sizeof(ushort), BufferUsage.IndexBuffer));
            _xOffsetBuffer
                = _factory.CreateBuffer(new BufferDescription(_xOffset.LengthUnsigned() * sizeof(float), BufferUsage.VertexBuffer));

            // fill buffers with data
            GraphicsDevice.UpdateBuffer(_vertexBuffer, 0, coloredQuad.Vertices);
            GraphicsDevice.UpdateBuffer(_indexBuffer, 0, quadIndicies);
            GraphicsDevice.UpdateBuffer(_xOffsetBuffer, 0, _xOffset);
            GraphicsDevice.UpdateBuffer(_cameraProjViewBuffer, 0, Camera.ViewMatrix);
            GraphicsDevice.UpdateBuffer(_cameraProjViewBuffer, 64, Camera.ProjectionMatrix);

            VertexLayoutDescription vertexLayout
                = new VertexLayoutDescription(
                      new VertexElementDescription("Position", VertexElementSemantic.Position, VertexElementFormat.Float2),
                      new VertexElementDescription("Color", VertexElementSemantic.Color, VertexElementFormat.Float4)
                      );

            VertexElementDescription vertexElementPerInstance
                = new VertexElementDescription("xOff", VertexElementSemantic.Position, VertexElementFormat.Float1);

            VertexLayoutDescription vertexLayoutPerInstance
                = new VertexLayoutDescription(
                      stride: 4,
                      instanceStepRate: 1,
                      elements: new VertexElementDescription[] { vertexElementPerInstance }
                      );

            _vertexShader   = IO.LoadShader("OffsetXNDCColor", ShaderStages.Vertex, GraphicsDevice);
            _fragmentShader = IO.LoadShader("Color", ShaderStages.Fragment, GraphicsDevice);

            GraphicsPipelineDescription pipelineDescription = new GraphicsPipelineDescription()
            {
                BlendState        = BlendStateDescription.SingleOverrideBlend,
                DepthStencilState = new DepthStencilStateDescription(
                    depthTestEnabled: true,
                    depthWriteEnabled: true,
                    comparisonKind: ComparisonKind.LessEqual),
                RasterizerState = new RasterizerStateDescription(
                    cullMode: FaceCullMode.Back,
                    fillMode: PolygonFillMode.Solid,
                    frontFace: FrontFace.Clockwise,
                    depthClipEnabled: true,
                    scissorTestEnabled: false
                    ),
                PrimitiveTopology = PrimitiveTopology.TriangleStrip,
                ResourceLayouts   = new ResourceLayout[] { _resourceLayout },
                ShaderSet         = new ShaderSetDescription(
                    vertexLayouts: new VertexLayoutDescription[] { vertexLayout, vertexLayoutPerInstance },
                    shaders: new Shader[] { _vertexShader, _fragmentShader }
                    ),
                Outputs = GraphicsDevice.SwapchainFramebuffer.OutputDescription
            };

            _pipeline = _factory.CreateGraphicsPipeline(pipelineDescription);
        }
Пример #11
0
        public VkPipeline(VkGraphicsDevice gd, ref GraphicsPipelineDescription description)
            : base(ref description)
        {
            _gd = gd;
            IsComputePipeline = false;
            RefCount          = new ResourceRefCount(DisposeCore);

            VkGraphicsPipelineCreateInfo pipelineCI = VkGraphicsPipelineCreateInfo.New();

            // Blend State
            VkPipelineColorBlendStateCreateInfo blendStateCI = VkPipelineColorBlendStateCreateInfo.New();
            int attachmentsCount = description.BlendState.AttachmentStates.Length;
            VkPipelineColorBlendAttachmentState *attachmentsPtr
                = stackalloc VkPipelineColorBlendAttachmentState[attachmentsCount];

            for (int i = 0; i < attachmentsCount; i++)
            {
                BlendAttachmentDescription          vdDesc          = description.BlendState.AttachmentStates[i];
                VkPipelineColorBlendAttachmentState attachmentState = new VkPipelineColorBlendAttachmentState();
                attachmentState.srcColorBlendFactor = VkFormats.VdToVkBlendFactor(vdDesc.SourceColorFactor);
                attachmentState.dstColorBlendFactor = VkFormats.VdToVkBlendFactor(vdDesc.DestinationColorFactor);
                attachmentState.colorBlendOp        = VkFormats.VdToVkBlendOp(vdDesc.ColorFunction);
                attachmentState.srcAlphaBlendFactor = VkFormats.VdToVkBlendFactor(vdDesc.SourceAlphaFactor);
                attachmentState.dstAlphaBlendFactor = VkFormats.VdToVkBlendFactor(vdDesc.DestinationAlphaFactor);
                attachmentState.alphaBlendOp        = VkFormats.VdToVkBlendOp(vdDesc.AlphaFunction);
                attachmentState.blendEnable         = vdDesc.BlendEnabled;
                attachmentState.colorWriteMask      = VkColorComponentFlags.R | VkColorComponentFlags.G | VkColorComponentFlags.B | VkColorComponentFlags.A;
                attachmentsPtr[i] = attachmentState;
            }

            blendStateCI.attachmentCount = (uint)attachmentsCount;
            blendStateCI.pAttachments    = attachmentsPtr;
            RgbaFloat blendFactor = description.BlendState.BlendFactor;

            blendStateCI.blendConstants_0 = blendFactor.R;
            blendStateCI.blendConstants_1 = blendFactor.G;
            blendStateCI.blendConstants_2 = blendFactor.B;
            blendStateCI.blendConstants_3 = blendFactor.A;

            pipelineCI.pColorBlendState = &blendStateCI;

            // Rasterizer State
            RasterizerStateDescription             rsDesc = description.RasterizerState;
            VkPipelineRasterizationStateCreateInfo rsCI   = VkPipelineRasterizationStateCreateInfo.New();

            rsCI.cullMode         = VkFormats.VdToVkCullMode(rsDesc.CullMode);
            rsCI.polygonMode      = VkFormats.VdToVkPolygonMode(rsDesc.FillMode);
            rsCI.depthClampEnable = !rsDesc.DepthClipEnabled;
            rsCI.frontFace        = rsDesc.FrontFace == FrontFace.Clockwise ? VkFrontFace.Clockwise : VkFrontFace.CounterClockwise;
            rsCI.lineWidth        = 1f;

            pipelineCI.pRasterizationState = &rsCI;

            ScissorTestEnabled = rsDesc.ScissorTestEnabled;

            // Dynamic State
            VkPipelineDynamicStateCreateInfo dynamicStateCI = VkPipelineDynamicStateCreateInfo.New();
            VkDynamicState *dynamicStates = stackalloc VkDynamicState[2];

            dynamicStates[0] = VkDynamicState.Viewport;
            dynamicStates[1] = VkDynamicState.Scissor;
            dynamicStateCI.dynamicStateCount = 2;
            dynamicStateCI.pDynamicStates    = dynamicStates;

            pipelineCI.pDynamicState = &dynamicStateCI;

            // Depth Stencil State
            DepthStencilStateDescription          vdDssDesc = description.DepthStencilState;
            VkPipelineDepthStencilStateCreateInfo dssCI     = VkPipelineDepthStencilStateCreateInfo.New();

            dssCI.depthWriteEnable  = vdDssDesc.DepthWriteEnabled;
            dssCI.depthTestEnable   = vdDssDesc.DepthTestEnabled;
            dssCI.depthCompareOp    = VkFormats.VdToVkCompareOp(vdDssDesc.DepthComparison);
            dssCI.stencilTestEnable = vdDssDesc.StencilTestEnabled;

            dssCI.front.failOp      = VkFormats.VdToVkStencilOp(vdDssDesc.StencilFront.Fail);
            dssCI.front.passOp      = VkFormats.VdToVkStencilOp(vdDssDesc.StencilFront.Pass);
            dssCI.front.depthFailOp = VkFormats.VdToVkStencilOp(vdDssDesc.StencilFront.DepthFail);
            dssCI.front.compareOp   = VkFormats.VdToVkCompareOp(vdDssDesc.StencilFront.Comparison);
            dssCI.front.compareMask = vdDssDesc.StencilReadMask;
            dssCI.front.writeMask   = vdDssDesc.StencilWriteMask;
            dssCI.front.reference   = vdDssDesc.StencilReference;

            dssCI.back.failOp      = VkFormats.VdToVkStencilOp(vdDssDesc.StencilBack.Fail);
            dssCI.back.passOp      = VkFormats.VdToVkStencilOp(vdDssDesc.StencilBack.Pass);
            dssCI.back.depthFailOp = VkFormats.VdToVkStencilOp(vdDssDesc.StencilBack.DepthFail);
            dssCI.back.compareOp   = VkFormats.VdToVkCompareOp(vdDssDesc.StencilBack.Comparison);
            dssCI.back.compareMask = vdDssDesc.StencilReadMask;
            dssCI.back.writeMask   = vdDssDesc.StencilWriteMask;
            dssCI.back.reference   = vdDssDesc.StencilReference;

            pipelineCI.pDepthStencilState = &dssCI;

            // Multisample
            VkPipelineMultisampleStateCreateInfo multisampleCI = VkPipelineMultisampleStateCreateInfo.New();
            VkSampleCountFlags vkSampleCount = VkFormats.VdToVkSampleCount(description.Outputs.SampleCount);

            multisampleCI.rasterizationSamples  = vkSampleCount;
            multisampleCI.alphaToCoverageEnable = description.BlendState.AlphaToCoverageEnabled;

            pipelineCI.pMultisampleState = &multisampleCI;

            // Input Assembly
            VkPipelineInputAssemblyStateCreateInfo inputAssemblyCI = VkPipelineInputAssemblyStateCreateInfo.New();

            inputAssemblyCI.topology = VkFormats.VdToVkPrimitiveTopology(description.PrimitiveTopology);

            pipelineCI.pInputAssemblyState = &inputAssemblyCI;

            // Vertex Input State
            VkPipelineVertexInputStateCreateInfo vertexInputCI = VkPipelineVertexInputStateCreateInfo.New();

            VertexLayoutDescription[] inputDescriptions = description.ShaderSet.VertexLayouts;
            uint bindingCount   = (uint)inputDescriptions.Length;
            uint attributeCount = 0;

            for (int i = 0; i < inputDescriptions.Length; i++)
            {
                attributeCount += (uint)inputDescriptions[i].Elements.Length;
            }
            VkVertexInputBindingDescription *  bindingDescs   = stackalloc VkVertexInputBindingDescription[(int)bindingCount];
            VkVertexInputAttributeDescription *attributeDescs = stackalloc VkVertexInputAttributeDescription[(int)attributeCount];

            int targetIndex    = 0;
            int targetLocation = 0;

            for (int binding = 0; binding < inputDescriptions.Length; binding++)
            {
                VertexLayoutDescription inputDesc = inputDescriptions[binding];
                bindingDescs[binding] = new VkVertexInputBindingDescription()
                {
                    binding   = (uint)binding,
                    inputRate = (inputDesc.InstanceStepRate != 0) ? VkVertexInputRate.Instance : VkVertexInputRate.Vertex,
                    stride    = inputDesc.Stride
                };

                uint currentOffset = 0;
                for (int location = 0; location < inputDesc.Elements.Length; location++)
                {
                    VertexElementDescription inputElement = inputDesc.Elements[location];

                    attributeDescs[targetIndex] = new VkVertexInputAttributeDescription()
                    {
                        format   = VkFormats.VdToVkVertexElementFormat(inputElement.Format),
                        binding  = (uint)binding,
                        location = (uint)(targetLocation + location),
                        offset   = inputElement.Offset != 0 ? inputElement.Offset : currentOffset
                    };

                    targetIndex   += 1;
                    currentOffset += FormatHelpers.GetSizeInBytes(inputElement.Format);
                }

                targetLocation += inputDesc.Elements.Length;
            }

            vertexInputCI.vertexBindingDescriptionCount   = bindingCount;
            vertexInputCI.pVertexBindingDescriptions      = bindingDescs;
            vertexInputCI.vertexAttributeDescriptionCount = attributeCount;
            vertexInputCI.pVertexAttributeDescriptions    = attributeDescs;

            pipelineCI.pVertexInputState = &vertexInputCI;

            // Shader Stage

            VkSpecializationInfo specializationInfo;

            SpecializationConstant[] specDescs = description.ShaderSet.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[] shaders = description.ShaderSet.Shaders;
            StackList <VkPipelineShaderStageCreateInfo> stages = new StackList <VkPipelineShaderStageCreateInfo>();

            foreach (Shader shader in shaders)
            {
                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.pName = new FixedUtf8String(shader.EntryPoint); // TODO: DONT ALLOCATE HERE
                stageCI.pSpecializationInfo = &specializationInfo;
                stages.Add(stageCI);
            }

            pipelineCI.stageCount = stages.Count;
            pipelineCI.pStages    = (VkPipelineShaderStageCreateInfo *)stages.Data;

            // ViewportState
            VkPipelineViewportStateCreateInfo viewportStateCI = VkPipelineViewportStateCreateInfo.New();

            viewportStateCI.viewportCount = 1;
            viewportStateCI.scissorCount  = 1;

            pipelineCI.pViewportState = &viewportStateCI;

            // 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;

            // Create fake RenderPass for compatibility.

            VkRenderPassCreateInfo renderPassCI = VkRenderPassCreateInfo.New();
            OutputDescription      outputDesc   = description.Outputs;
            StackList <VkAttachmentDescription, Size512Bytes> attachments = new StackList <VkAttachmentDescription, Size512Bytes>();

            // TODO: A huge portion of this next part is duplicated in VkFramebuffer.cs.

            StackList <VkAttachmentDescription> colorAttachmentDescs = new StackList <VkAttachmentDescription>();
            StackList <VkAttachmentReference>   colorAttachmentRefs  = new StackList <VkAttachmentReference>();

            for (uint i = 0; i < outputDesc.ColorAttachments.Length; i++)
            {
                colorAttachmentDescs[i].format         = VkFormats.VdToVkPixelFormat(outputDesc.ColorAttachments[i].Format);
                colorAttachmentDescs[i].samples        = vkSampleCount;
                colorAttachmentDescs[i].loadOp         = VkAttachmentLoadOp.DontCare;
                colorAttachmentDescs[i].storeOp        = VkAttachmentStoreOp.Store;
                colorAttachmentDescs[i].stencilLoadOp  = VkAttachmentLoadOp.DontCare;
                colorAttachmentDescs[i].stencilStoreOp = VkAttachmentStoreOp.DontCare;
                colorAttachmentDescs[i].initialLayout  = VkImageLayout.Undefined;
                colorAttachmentDescs[i].finalLayout    = VkImageLayout.ShaderReadOnlyOptimal;
                attachments.Add(colorAttachmentDescs[i]);

                colorAttachmentRefs[i].attachment = i;
                colorAttachmentRefs[i].layout     = VkImageLayout.ColorAttachmentOptimal;
            }

            VkAttachmentDescription depthAttachmentDesc = new VkAttachmentDescription();
            VkAttachmentReference   depthAttachmentRef  = new VkAttachmentReference();

            if (outputDesc.DepthAttachment != null)
            {
                PixelFormat depthFormat = outputDesc.DepthAttachment.Value.Format;
                bool        hasStencil  = FormatHelpers.IsStencilFormat(depthFormat);
                depthAttachmentDesc.format         = VkFormats.VdToVkPixelFormat(outputDesc.DepthAttachment.Value.Format, toDepthFormat: true);
                depthAttachmentDesc.samples        = vkSampleCount;
                depthAttachmentDesc.loadOp         = VkAttachmentLoadOp.DontCare;
                depthAttachmentDesc.storeOp        = VkAttachmentStoreOp.Store;
                depthAttachmentDesc.stencilLoadOp  = VkAttachmentLoadOp.DontCare;
                depthAttachmentDesc.stencilStoreOp = hasStencil ? VkAttachmentStoreOp.Store : VkAttachmentStoreOp.DontCare;
                depthAttachmentDesc.initialLayout  = VkImageLayout.Undefined;
                depthAttachmentDesc.finalLayout    = VkImageLayout.DepthStencilAttachmentOptimal;

                depthAttachmentRef.attachment = (uint)outputDesc.ColorAttachments.Length;
                depthAttachmentRef.layout     = VkImageLayout.DepthStencilAttachmentOptimal;
            }

            VkSubpassDescription subpass = new VkSubpassDescription();

            subpass.pipelineBindPoint    = VkPipelineBindPoint.Graphics;
            subpass.colorAttachmentCount = (uint)outputDesc.ColorAttachments.Length;
            subpass.pColorAttachments    = (VkAttachmentReference *)colorAttachmentRefs.Data;
            for (int i = 0; i < colorAttachmentDescs.Count; i++)
            {
                attachments.Add(colorAttachmentDescs[i]);
            }

            if (outputDesc.DepthAttachment != null)
            {
                subpass.pDepthStencilAttachment = &depthAttachmentRef;
                attachments.Add(depthAttachmentDesc);
            }

            VkSubpassDependency subpassDependency = new VkSubpassDependency();

            subpassDependency.srcSubpass    = SubpassExternal;
            subpassDependency.srcStageMask  = VkPipelineStageFlags.ColorAttachmentOutput;
            subpassDependency.dstStageMask  = VkPipelineStageFlags.ColorAttachmentOutput;
            subpassDependency.dstAccessMask = VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite;

            renderPassCI.attachmentCount = attachments.Count;
            renderPassCI.pAttachments    = (VkAttachmentDescription *)attachments.Data;
            renderPassCI.subpassCount    = 1;
            renderPassCI.pSubpasses      = &subpass;
            renderPassCI.dependencyCount = 1;
            renderPassCI.pDependencies   = &subpassDependency;

            VkResult creationResult = vkCreateRenderPass(_gd.Device, ref renderPassCI, null, out _renderPass);

            CheckResult(creationResult);

            pipelineCI.renderPass = _renderPass;

            VkResult result = vkCreateGraphicsPipelines(_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;
            }
        }
Пример #12
0
        public MTLPipeline(ref GraphicsPipelineDescription description, MTLGraphicsDevice gd)
            : base(ref description)
        {
            PrimitiveType        = MTLFormats.VdToMTLPrimitiveTopology(description.PrimitiveTopology);
            ResourceLayouts      = new MTLResourceLayout[description.ResourceLayouts.Length];
            NonVertexBufferCount = 0;
            for (int i = 0; i < ResourceLayouts.Length; i++)
            {
                ResourceLayouts[i]    = Util.AssertSubtype <ResourceLayout, MTLResourceLayout>(description.ResourceLayouts[i]);
                NonVertexBufferCount += ResourceLayouts[i].BufferCount;
            }
            ResourceBindingModel = description.ResourceBindingModel ?? gd.ResourceBindingModel;

            CullMode           = MTLFormats.VdToMTLCullMode(description.RasterizerState.CullMode);
            FrontFace          = MTLFormats.VdVoMTLFrontFace(description.RasterizerState.FrontFace);
            FillMode           = MTLFormats.VdToMTLFillMode(description.RasterizerState.FillMode);
            ScissorTestEnabled = description.RasterizerState.ScissorTestEnabled;

            MTLRenderPipelineDescriptor mtlDesc = MTLRenderPipelineDescriptor.New();

            foreach (Shader shader in description.ShaderSet.Shaders)
            {
                MTLShader   mtlShader = Util.AssertSubtype <Shader, MTLShader>(shader);
                MTLFunction specializedFunction;

                if (mtlShader.HasFunctionConstants)
                {
                    // Need to create specialized MTLFunction.
                    MTLFunctionConstantValues constantValues = CreateConstantValues(description.ShaderSet.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;
                }

                if (shader.Stage == ShaderStages.Vertex)
                {
                    mtlDesc.vertexFunction = specializedFunction;
                }
                else if (shader.Stage == ShaderStages.Fragment)
                {
                    mtlDesc.fragmentFunction = specializedFunction;
                }
            }

            // Vertex layouts
            VertexLayoutDescription[] vdVertexLayouts  = description.ShaderSet.VertexLayouts;
            MTLVertexDescriptor       vertexDescriptor = mtlDesc.vertexDescriptor;

            for (uint i = 0; i < vdVertexLayouts.Length; i++)
            {
                uint layoutIndex = ResourceBindingModel == ResourceBindingModel.Improved
                    ? NonVertexBufferCount + i
                    : i;
                MTLVertexBufferLayoutDescriptor mtlLayout = vertexDescriptor.layouts[layoutIndex];
                mtlLayout.stride = (UIntPtr)vdVertexLayouts[i].Stride;
                uint stepRate = vdVertexLayouts[i].InstanceStepRate;
                mtlLayout.stepFunction = stepRate == 0 ? MTLVertexStepFunction.PerVertex : MTLVertexStepFunction.PerInstance;
                mtlLayout.stepRate     = (UIntPtr)Math.Max(1, stepRate);
            }

            uint element = 0;

            for (uint i = 0; i < vdVertexLayouts.Length; i++)
            {
                uint offset = 0;
                VertexLayoutDescription vdDesc = vdVertexLayouts[i];
                for (uint j = 0; j < vdDesc.Elements.Length; j++)
                {
                    VertexElementDescription     elementDesc  = vdDesc.Elements[j];
                    MTLVertexAttributeDescriptor mtlAttribute = vertexDescriptor.attributes[element];
                    mtlAttribute.bufferIndex = (UIntPtr)(ResourceBindingModel == ResourceBindingModel.Improved
                        ? NonVertexBufferCount + i
                        : i);
                    mtlAttribute.format = MTLFormats.VdToMTLVertexFormat(elementDesc.Format);
                    mtlAttribute.offset = elementDesc.Offset != 0 ? (UIntPtr)elementDesc.Offset : (UIntPtr)offset;
                    offset  += FormatHelpers.GetSizeInBytes(elementDesc.Format);
                    element += 1;
                }
            }

            VertexBufferCount = (uint)vdVertexLayouts.Length;

            // Outputs
            OutputDescription     outputs        = description.Outputs;
            BlendStateDescription blendStateDesc = description.BlendState;

            BlendColor = blendStateDesc.BlendFactor;

            if (outputs.SampleCount != TextureSampleCount.Count1)
            {
                mtlDesc.sampleCount = (UIntPtr)FormatHelpers.GetSampleCountUInt32(outputs.SampleCount);
            }

            if (outputs.DepthAttachment != null)
            {
                PixelFormat    depthFormat    = outputs.DepthAttachment.Value.Format;
                MTLPixelFormat mtlDepthFormat = MTLFormats.VdToMTLPixelFormat(depthFormat, true);
                mtlDesc.depthAttachmentPixelFormat = mtlDepthFormat;
                if ((FormatHelpers.IsStencilFormat(depthFormat)))
                {
                    HasStencil = true;
                    mtlDesc.stencilAttachmentPixelFormat = mtlDepthFormat;
                }
            }
            for (uint i = 0; i < outputs.ColorAttachments.Length; i++)
            {
                BlendAttachmentDescription attachmentBlendDesc       = blendStateDesc.AttachmentStates[i];
                MTLRenderPipelineColorAttachmentDescriptor colorDesc = mtlDesc.colorAttachments[i];
                colorDesc.pixelFormat                 = MTLFormats.VdToMTLPixelFormat(outputs.ColorAttachments[i].Format, false);
                colorDesc.blendingEnabled             = attachmentBlendDesc.BlendEnabled;
                colorDesc.alphaBlendOperation         = MTLFormats.VdToMTLBlendOp(attachmentBlendDesc.AlphaFunction);
                colorDesc.sourceAlphaBlendFactor      = MTLFormats.VdToMTLBlendFactor(attachmentBlendDesc.SourceAlphaFactor);
                colorDesc.destinationAlphaBlendFactor = MTLFormats.VdToMTLBlendFactor(attachmentBlendDesc.DestinationAlphaFactor);

                colorDesc.rgbBlendOperation         = MTLFormats.VdToMTLBlendOp(attachmentBlendDesc.ColorFunction);
                colorDesc.sourceRGBBlendFactor      = MTLFormats.VdToMTLBlendFactor(attachmentBlendDesc.SourceColorFactor);
                colorDesc.destinationRGBBlendFactor = MTLFormats.VdToMTLBlendFactor(attachmentBlendDesc.DestinationColorFactor);
            }

            RenderPipelineState = gd.Device.newRenderPipelineStateWithDescriptor(mtlDesc);
            ObjectiveCRuntime.release(mtlDesc.NativePtr);

            if (outputs.DepthAttachment != null)
            {
                MTLDepthStencilDescriptor depthDescriptor = MTLUtil.AllocInit <MTLDepthStencilDescriptor>(
                    nameof(MTLDepthStencilDescriptor));
                depthDescriptor.depthCompareFunction = MTLFormats.VdToMTLCompareFunction(
                    description.DepthStencilState.DepthComparison);
                depthDescriptor.depthWriteEnabled = description.DepthStencilState.DepthWriteEnabled;

                bool stencilEnabled = description.DepthStencilState.StencilTestEnabled;
                if (stencilEnabled)
                {
                    StencilReference = description.DepthStencilState.StencilReference;

                    StencilBehaviorDescription vdFrontDesc = description.DepthStencilState.StencilFront;
                    MTLStencilDescriptor       front       = MTLUtil.AllocInit <MTLStencilDescriptor>(nameof(MTLStencilDescriptor));
                    front.readMask                   = stencilEnabled ? description.DepthStencilState.StencilReadMask : 0u;
                    front.writeMask                  = stencilEnabled ? description.DepthStencilState.StencilWriteMask : 0u;
                    front.depthFailureOperation      = MTLFormats.VdToMTLStencilOperation(vdFrontDesc.DepthFail);
                    front.stencilFailureOperation    = MTLFormats.VdToMTLStencilOperation(vdFrontDesc.Fail);
                    front.depthStencilPassOperation  = MTLFormats.VdToMTLStencilOperation(vdFrontDesc.Pass);
                    front.stencilCompareFunction     = MTLFormats.VdToMTLCompareFunction(vdFrontDesc.Comparison);
                    depthDescriptor.frontFaceStencil = front;

                    StencilBehaviorDescription vdBackDesc = description.DepthStencilState.StencilBack;
                    MTLStencilDescriptor       back       = MTLUtil.AllocInit <MTLStencilDescriptor>(nameof(MTLStencilDescriptor));
                    back.readMask                   = stencilEnabled ? description.DepthStencilState.StencilReadMask : 0u;
                    back.writeMask                  = stencilEnabled ? description.DepthStencilState.StencilWriteMask : 0u;
                    back.depthFailureOperation      = MTLFormats.VdToMTLStencilOperation(vdBackDesc.DepthFail);
                    back.stencilFailureOperation    = MTLFormats.VdToMTLStencilOperation(vdBackDesc.Fail);
                    back.depthStencilPassOperation  = MTLFormats.VdToMTLStencilOperation(vdBackDesc.Pass);
                    back.stencilCompareFunction     = MTLFormats.VdToMTLCompareFunction(vdBackDesc.Comparison);
                    depthDescriptor.backFaceStencil = back;

                    ObjectiveCRuntime.release(front.NativePtr);
                    ObjectiveCRuntime.release(back.NativePtr);
                }

                DepthStencilState = gd.Device.newDepthStencilStateWithDescriptor(depthDescriptor);
                ObjectiveCRuntime.release(depthDescriptor.NativePtr);
            }

            DepthClipMode = description.DepthStencilState.DepthTestEnabled ? MTLDepthClipMode.Clip : MTLDepthClipMode.Clamp;
        }
 private void WriteVertexElementDesc(BinaryWriter writer, VertexElementDescription desc)
 {
     writer.Write(desc.Name);
     writer.WriteEnum(desc.Semantic);
     writer.WriteEnum(desc.Format);
 }
Пример #14
0
        public VkPipeline(VkGraphicsDevice gd, ref PipelineDescription description)
        {
            _gd = gd;

            VkGraphicsPipelineCreateInfo pipelineCI = VkGraphicsPipelineCreateInfo.New();

            // Blend State
            VkPipelineColorBlendStateCreateInfo blendStateCI = VkPipelineColorBlendStateCreateInfo.New();
            int attachmentsCount = description.BlendState.AttachmentStates.Length;
            VkPipelineColorBlendAttachmentState *attachmentsPtr
                = stackalloc VkPipelineColorBlendAttachmentState[attachmentsCount];

            for (int i = 0; i < attachmentsCount; i++)
            {
                BlendAttachmentDescription          vdDesc          = description.BlendState.AttachmentStates[i];
                VkPipelineColorBlendAttachmentState attachmentState = new VkPipelineColorBlendAttachmentState();
                attachmentState.srcColorBlendFactor = VkFormats.VdToVkBlendFactor(vdDesc.SourceColorFactor);
                attachmentState.dstColorBlendFactor = VkFormats.VdToVkBlendFactor(vdDesc.DestinationColorFactor);
                attachmentState.colorBlendOp        = VkFormats.VdToVkBlendOp(vdDesc.ColorFunction);
                attachmentState.srcAlphaBlendFactor = VkFormats.VdToVkBlendFactor(vdDesc.SourceAlphaFactor);
                attachmentState.dstAlphaBlendFactor = VkFormats.VdToVkBlendFactor(vdDesc.DestinationAlphaFactor);
                attachmentState.alphaBlendOp        = VkFormats.VdToVkBlendOp(vdDesc.AlphaFunction);
                attachmentState.blendEnable         = vdDesc.BlendEnabled;
                attachmentState.colorWriteMask      = VkColorComponentFlags.R | VkColorComponentFlags.G | VkColorComponentFlags.B | VkColorComponentFlags.A;
                attachmentsPtr[i] = attachmentState;
            }

            blendStateCI.attachmentCount = (uint)attachmentsCount;
            blendStateCI.pAttachments    = attachmentsPtr;
            RgbaFloat blendFactor = description.BlendState.BlendFactor;

            blendStateCI.blendConstants_0 = blendFactor.R;
            blendStateCI.blendConstants_1 = blendFactor.G;
            blendStateCI.blendConstants_2 = blendFactor.B;
            blendStateCI.blendConstants_3 = blendFactor.A;

            pipelineCI.pColorBlendState = &blendStateCI;

            // Rasterizer State
            RasterizerStateDescription             rsDesc = description.RasterizerState;
            VkPipelineRasterizationStateCreateInfo rsCI   = VkPipelineRasterizationStateCreateInfo.New();

            rsCI.cullMode         = VkFormats.VdToVkCullMode(rsDesc.CullMode);
            rsCI.polygonMode      = VkFormats.VdToVkPolygonMode(rsDesc.FillMode);
            rsCI.depthClampEnable = !rsDesc.DepthClipEnabled;
            rsCI.frontFace        = VkFrontFace.Clockwise;
            rsCI.lineWidth        = 1f;

            pipelineCI.pRasterizationState = &rsCI;

            // Dynamic State
            VkPipelineDynamicStateCreateInfo dynamicStateCI = VkPipelineDynamicStateCreateInfo.New();
            VkDynamicState *dynamicStates = stackalloc VkDynamicState[2];

            dynamicStates[0] = VkDynamicState.Viewport;
            dynamicStates[1] = VkDynamicState.Scissor;
            dynamicStateCI.dynamicStateCount = 2;
            dynamicStateCI.pDynamicStates    = dynamicStates;

            pipelineCI.pDynamicState = &dynamicStateCI;

            // Depth Stencil State
            DepthStencilStateDescription          vdDssDesc = description.DepthStencilState;
            VkPipelineDepthStencilStateCreateInfo dssCI     = VkPipelineDepthStencilStateCreateInfo.New();

            dssCI.depthWriteEnable = vdDssDesc.DepthWriteEnabled;
            dssCI.depthTestEnable  = vdDssDesc.DepthTestEnabled;
            dssCI.depthCompareOp   = VkFormats.VdToVkCompareOp(vdDssDesc.ComparisonKind);

            pipelineCI.pDepthStencilState = &dssCI;

            // Multisample
            VkPipelineMultisampleStateCreateInfo multisampleCI = VkPipelineMultisampleStateCreateInfo.New();

            multisampleCI.rasterizationSamples = VkSampleCountFlags.Count1;

            pipelineCI.pMultisampleState = &multisampleCI;

            // Input Assembly
            VkPipelineInputAssemblyStateCreateInfo inputAssemblyCI = VkPipelineInputAssemblyStateCreateInfo.New();

            inputAssemblyCI.topology = VkFormats.VdToVkPrimitiveTopology(description.PrimitiveTopology);

            pipelineCI.pInputAssemblyState = &inputAssemblyCI;

            // Vertex Input State
            VkPipelineVertexInputStateCreateInfo vertexInputCI = VkPipelineVertexInputStateCreateInfo.New();

            VertexLayoutDescription[] inputDescriptions = description.ShaderSet.VertexLayouts;
            uint bindingCount   = (uint)inputDescriptions.Length;
            uint attributeCount = 0;

            for (int i = 0; i < inputDescriptions.Length; i++)
            {
                attributeCount += (uint)inputDescriptions[i].Elements.Length;
            }
            VkVertexInputBindingDescription *  bindingDescs   = stackalloc VkVertexInputBindingDescription[(int)bindingCount];
            VkVertexInputAttributeDescription *attributeDescs = stackalloc VkVertexInputAttributeDescription[(int)attributeCount];

            int targetIndex    = 0;
            int targetLocation = 0;

            for (int binding = 0; binding < inputDescriptions.Length; binding++)
            {
                VertexLayoutDescription inputDesc = inputDescriptions[binding];
                bindingDescs[targetIndex] = new VkVertexInputBindingDescription()
                {
                    binding   = (uint)binding,
                    inputRate = (inputDesc.Elements[0].InstanceStepRate != 0) ? VkVertexInputRate.Instance : VkVertexInputRate.Vertex,
                    stride    = inputDesc.Stride
                };

                uint currentOffset = 0;
                for (int location = 0; location < inputDesc.Elements.Length; location++)
                {
                    VertexElementDescription inputElement = inputDesc.Elements[location];

                    attributeDescs[targetIndex] = new VkVertexInputAttributeDescription()
                    {
                        format   = VkFormats.VdToVkVertexElementFormat(inputElement.Format),
                        binding  = (uint)binding,
                        location = (uint)(targetLocation + location),
                        offset   = currentOffset
                    };

                    targetIndex   += 1;
                    currentOffset += FormatHelpers.GetSizeInBytes(inputElement.Format);
                }

                targetLocation += inputDesc.Elements.Length;
            }

            vertexInputCI.vertexBindingDescriptionCount   = bindingCount;
            vertexInputCI.pVertexBindingDescriptions      = bindingDescs;
            vertexInputCI.vertexAttributeDescriptionCount = attributeCount;
            vertexInputCI.pVertexAttributeDescriptions    = attributeDescs;

            pipelineCI.pVertexInputState = &vertexInputCI;

            // Shader Stage
            ShaderStageDescription[] stageDescs = description.ShaderSet.ShaderStages;
            StackList <VkPipelineShaderStageCreateInfo> stages = new StackList <VkPipelineShaderStageCreateInfo>();

            foreach (ShaderStageDescription stageDesc in stageDescs)
            {
                VkShader vkShader = Util.AssertSubtype <Shader, VkShader>(stageDesc.Shader);
                VkPipelineShaderStageCreateInfo stageCI = VkPipelineShaderStageCreateInfo.New();
                stageCI.module = vkShader.ShaderModule;
                stageCI.stage  = VkFormats.VdToVkShaderStages(stageDesc.Stage);
                stageCI.pName  = CommonStrings.main; // Meh
                stages.Add(stageCI);
            }

            pipelineCI.stageCount = stages.Count;
            pipelineCI.pStages    = (VkPipelineShaderStageCreateInfo *)stages.Data;

            // ViewportState
            VkPipelineViewportStateCreateInfo viewportStateCI = VkPipelineViewportStateCreateInfo.New();

            viewportStateCI.viewportCount = 1;
            viewportStateCI.scissorCount  = 1;

            pipelineCI.pViewportState = &viewportStateCI;

            // 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;

            // Create fake RenderPass for compatibility.
            VkRenderPassCreateInfo renderPassCI = VkRenderPassCreateInfo.New();
            OutputDescription      outputDesc   = description.Outputs;

            if (outputDesc.ColorAttachments.Length > 1)
            {
                throw new NotImplementedException("Laziness");
            }

            VkAttachmentDescription colorAttachmentDesc = new VkAttachmentDescription();

            colorAttachmentDesc.format = outputDesc.ColorAttachments.Length > 0
                ? VkFormats.VdToVkPixelFormat(outputDesc.ColorAttachments[0].Format) : 0;
            colorAttachmentDesc.samples        = VkSampleCountFlags.Count1;
            colorAttachmentDesc.loadOp         = VkAttachmentLoadOp.Clear;
            colorAttachmentDesc.storeOp        = VkAttachmentStoreOp.Store;
            colorAttachmentDesc.stencilLoadOp  = VkAttachmentLoadOp.DontCare;
            colorAttachmentDesc.stencilStoreOp = VkAttachmentStoreOp.DontCare;
            colorAttachmentDesc.initialLayout  = VkImageLayout.Undefined;
            colorAttachmentDesc.finalLayout    = VkImageLayout.PresentSrcKHR;

            VkAttachmentReference colorAttachmentRef = new VkAttachmentReference();

            colorAttachmentRef.attachment = 0;
            colorAttachmentRef.layout     = VkImageLayout.ColorAttachmentOptimal;

            VkAttachmentDescription depthAttachmentDesc = new VkAttachmentDescription();
            VkAttachmentReference   depthAttachmentRef  = new VkAttachmentReference();

            if (outputDesc.DepthAttachment != null)
            {
                depthAttachmentDesc.format         = VkFormats.VdToVkPixelFormat(outputDesc.DepthAttachment.Value.Format, toDepthFormat: true);
                depthAttachmentDesc.samples        = VkSampleCountFlags.Count1;
                depthAttachmentDesc.loadOp         = VkAttachmentLoadOp.Clear;
                depthAttachmentDesc.storeOp        = VkAttachmentStoreOp.Store;
                depthAttachmentDesc.stencilLoadOp  = VkAttachmentLoadOp.DontCare;
                depthAttachmentDesc.stencilStoreOp = VkAttachmentStoreOp.DontCare;
                depthAttachmentDesc.initialLayout  = VkImageLayout.Undefined;
                depthAttachmentDesc.finalLayout    = VkImageLayout.DepthStencilAttachmentOptimal;

                depthAttachmentRef.attachment = outputDesc.ColorAttachments.Length == 0 ? 0u : 1u;
                depthAttachmentRef.layout     = VkImageLayout.DepthStencilAttachmentOptimal;
            }

            VkSubpassDescription subpass = new VkSubpassDescription();
            StackList <VkAttachmentDescription, Size512Bytes> attachments = new StackList <VkAttachmentDescription, Size512Bytes>();

            subpass.pipelineBindPoint = VkPipelineBindPoint.Graphics;
            if (outputDesc.ColorAttachments.Length > 0)
            {
                subpass.colorAttachmentCount = 1;
                subpass.pColorAttachments    = &colorAttachmentRef;
                attachments.Add(colorAttachmentDesc);
            }

            if (outputDesc.DepthAttachment != null)
            {
                subpass.pDepthStencilAttachment = &depthAttachmentRef;
                attachments.Add(depthAttachmentDesc);
            }

            VkSubpassDependency subpassDependency = new VkSubpassDependency();

            subpassDependency.srcSubpass    = SubpassExternal;
            subpassDependency.srcStageMask  = VkPipelineStageFlags.ColorAttachmentOutput;
            subpassDependency.dstStageMask  = VkPipelineStageFlags.ColorAttachmentOutput;
            subpassDependency.dstAccessMask = VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite;
            if (outputDesc.DepthAttachment != null)
            {
                subpassDependency.dstAccessMask |= VkAccessFlags.DepthStencilAttachmentRead | VkAccessFlags.DepthStencilAttachmentWrite;
            }

            renderPassCI.attachmentCount = attachments.Count;
            renderPassCI.pAttachments    = (VkAttachmentDescription *)attachments.Data;
            renderPassCI.subpassCount    = 1;
            renderPassCI.pSubpasses      = &subpass;
            renderPassCI.dependencyCount = 1;
            renderPassCI.pDependencies   = &subpassDependency;

            VkResult creationResult = vkCreateRenderPass(_gd.Device, ref renderPassCI, null, out _renderPass);

            CheckResult(creationResult);

            pipelineCI.renderPass = _renderPass;

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

            CheckResult(result);

            ResourceSetCount = (uint)description.ResourceLayouts.Length;
        }
Пример #15
0
        /// <summary>
        /// Cross-compiles the given vertex-fragment pair into some target language.
        /// </summary>
        /// <param name="vsBytes">The vertex shader's SPIR-V bytecode or ASCII-encoded GLSL source code.</param>
        /// <param name="fsBytes">The fragment shader's SPIR-V bytecode or ASCII-encoded GLSL source code.</param>
        /// <param name="target">The target language.</param>
        /// <param name="options">The options for shader translation.</param>
        /// <returns>A <see cref="VertexFragmentCompilationResult"/> containing the compiled output.</returns>
        public static unsafe VertexFragmentCompilationResult CompileVertexFragment(
            byte[] vsBytes,
            byte[] fsBytes,
            CrossCompileTarget target,
            CrossCompileOptions options)
        {
            int size1 = sizeof(CrossCompileInfo);
            int size2 = sizeof(InteropArray);

            byte[] vsSpirvBytes;
            byte[] fsSpirvBytes;

            if (Util.HasSpirvHeader(vsBytes))
            {
                vsSpirvBytes = vsBytes;
            }
            else
            {
                fixed(byte *sourceTextPtr = vsBytes)
                {
                    SpirvCompilationResult vsCompileResult = CompileGlslToSpirv(
                        (uint)vsBytes.Length,
                        sourceTextPtr,
                        string.Empty,
                        ShaderStages.Vertex,
                        target == CrossCompileTarget.GLSL || target == CrossCompileTarget.ESSL,
                        0,
                        null);

                    vsSpirvBytes = vsCompileResult.SpirvBytes;
                }
            }

            if (Util.HasSpirvHeader(fsBytes))
            {
                fsSpirvBytes = fsBytes;
            }
            else
            {
                fixed(byte *sourceTextPtr = fsBytes)
                {
                    SpirvCompilationResult fsCompileResult = CompileGlslToSpirv(
                        (uint)fsBytes.Length,
                        sourceTextPtr,
                        string.Empty,
                        ShaderStages.Fragment,
                        target == CrossCompileTarget.GLSL || target == CrossCompileTarget.ESSL,
                        0,
                        null);

                    fsSpirvBytes = fsCompileResult.SpirvBytes;
                }
            }

            int specConstantsCount = options.Specializations.Length;
            NativeSpecializationConstant *nativeSpecConstants = stackalloc NativeSpecializationConstant[specConstantsCount];

            for (int i = 0; i < specConstantsCount; i++)
            {
                nativeSpecConstants[i].ID       = options.Specializations[i].ID;
                nativeSpecConstants[i].Constant = options.Specializations[i].Data;
            }

            CrossCompileInfo info;

            info.Target                 = target;
            info.FixClipSpaceZ          = options.FixClipSpaceZ;
            info.InvertY                = options.InvertVertexOutputY;
            info.NormalizeResourceNames = options.NormalizeResourceNames;
            fixed(byte *vsBytesPtr = vsSpirvBytes)
            fixed(byte *fsBytesPtr = fsSpirvBytes)
            {
                info.VertexShader    = new InteropArray((uint)vsSpirvBytes.Length / 4, vsBytesPtr);
                info.FragmentShader  = new InteropArray((uint)fsSpirvBytes.Length / 4, fsBytesPtr);
                info.Specializations = new InteropArray((uint)specConstantsCount, nativeSpecConstants);

                CompilationResult *result = null;

                try
                {
                    result = VeldridSpirvNative.CrossCompile(&info);
                    if (!result->Succeeded)
                    {
                        throw new SpirvCompilationException(
                                  "Compilation failed: " + Util.GetString((byte *)result->GetData(0), result->GetLength(0)));
                    }

                    string vsCode = Util.GetString((byte *)result->GetData(0), result->GetLength(0));
                    string fsCode = Util.GetString((byte *)result->GetData(1), result->GetLength(1));

                    ReflectionInfo *reflInfo = &result->ReflectionInfo;

                    VertexElementDescription[] vertexElements = new VertexElementDescription[reflInfo->VertexElements.Count];
                    for (uint i = 0; i < reflInfo->VertexElements.Count; i++)
                    {
                        ref NativeVertexElementDescription nativeDesc
                            = ref reflInfo->VertexElements.Ref <NativeVertexElementDescription>(i);
                        vertexElements[i] = new VertexElementDescription(
                            Util.GetString((byte *)nativeDesc.Name.Data, nativeDesc.Name.Count),
                            nativeDesc.Semantic,
                            nativeDesc.Format,
                            nativeDesc.Offset);
                    }

                    ResourceLayoutDescription[] layouts = new ResourceLayoutDescription[reflInfo->ResourceLayouts.Count];
                    for (uint i = 0; i < reflInfo->ResourceLayouts.Count; i++)
                    {
                        ref NativeResourceLayoutDescription nativeDesc =
                            ref reflInfo->ResourceLayouts.Ref <NativeResourceLayoutDescription>(i);
                        layouts[i].Elements = new ResourceLayoutElementDescription[nativeDesc.ResourceElements.Count];
                        for (uint j = 0; j < nativeDesc.ResourceElements.Count; j++)
                        {
                            ref NativeResourceElementDescription elemDesc =
                                ref nativeDesc.ResourceElements.Ref <NativeResourceElementDescription>(j);
                            layouts[i].Elements[j] = new ResourceLayoutElementDescription(
                                Util.GetString((byte *)elemDesc.Name.Data, elemDesc.Name.Count),
                                elemDesc.Kind,
                                elemDesc.Stages,
                                elemDesc.Options);
                        }
                    }
Пример #16
0
        public static VeldridGeometry Create(IMesh mesh)
        {
            var gpuMesh = mesh.ToGpuMesh();
            var result  = new VeldridGeometry();
            var bufferViewToPrimitive    = new Dictionary <IBufferView, VeldridPrimitive>();
            var vertexBufferMemoryStream = new MemoryStream();

            result.IndexFormat = Veldrid.IndexFormat.UInt16;
            using (var vertexBufferWriter = new BinaryWriter(vertexBufferMemoryStream))
            {
                foreach (var bufferView in gpuMesh.BufferViews)
                {
                    var veldridPrimitive = new VeldridPrimitive();
                    veldridPrimitive.VertexBufferOffset = (uint)vertexBufferMemoryStream.Position;

                    var streamKeys = bufferView.GetStreams().Select(_ => new SortableStreamKey(_)).OrderBy(_ => _)
                                     .Select(_ => _.Key).ToList();
                    var elements  = new VertexElementDescription[streamKeys.Count];
                    var accessors = new IStreamAccessor[streamKeys.Count];
                    for (var index = 0; index < streamKeys.Count; index++)
                    {
                        var reader = accessors[index] = GetAccessor(bufferView, streamKeys[index]);
                        elements[index] = new VertexElementDescription(streamKeys[index].ToString(),
                                                                       VertexElementSemantic.TextureCoordinate, reader.VertexElementFormat);
                    }

                    var count = accessors[0].Count;
                    if (count > ushort.MaxValue)
                    {
                        result.IndexFormat = Veldrid.IndexFormat.UInt32;
                    }

                    for (var index = 0; index < count; index++)
                    {
                        for (var accessorIndex = 0; accessorIndex < accessors.Length; accessorIndex++)
                        {
                            accessors[accessorIndex].Write(index, vertexBufferWriter);
                        }
                    }

                    veldridPrimitive.VertexLayout = new VertexLayoutDescription(elements);
                    bufferViewToPrimitive.Add(bufferView, veldridPrimitive);
                }
            }
            result.VertexBuffer = new Memory <byte>(vertexBufferMemoryStream.ToArray());
            var indexBufferMemoryStream = new MemoryStream();

            result.Primitives = new VeldridPrimitive[gpuMesh.Primitives.Count];
            using (var indexBufferWriter = new BinaryWriter(indexBufferMemoryStream))
            {
                for (var primitiveIndex = 0; primitiveIndex < gpuMesh.Primitives.Count; primitiveIndex++)
                {
                    var primitive        = gpuMesh.Primitives[primitiveIndex];
                    var primitiveBase    = bufferViewToPrimitive[primitive.BufferView];
                    var veldridPrimitive = new VeldridPrimitive()
                    {
                        VertexBufferOffset = primitiveBase.VertexBufferOffset,
                        PrimitiveTopology  = GetTopology(primitive.Topology),
                        IndexBufferOffset  = (uint)indexBufferMemoryStream.Position,
                        VertexLayout       = primitiveBase.VertexLayout
                    };
                    if (result.IndexFormat == Veldrid.IndexFormat.UInt32)
                    {
                        foreach (var index in primitive)
                        {
                            indexBufferWriter.Write((uint)index);
                        }
                    }
                    else if (result.IndexFormat == Veldrid.IndexFormat.UInt16)
                    {
                        foreach (var index in primitive)
                        {
                            indexBufferWriter.Write((ushort)index);
                        }
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }
                    result.Primitives[primitiveIndex] = veldridPrimitive;
                }
            }

            result.IndexBuffer = new Memory <byte>(indexBufferMemoryStream.ToArray());

            return(result);
        }