Пример #1
0
        private void createSwapChain()
        {
            SwapChainSupportDetails swapChainSupport = querySwapChainSupport(physicalDevice);

            VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats);
            VkPresentModeKHR   presentMode   = chooseSwapPresentMode(swapChainSupport.presentModes);
            VkExtent2D         extent        = chooseSwapExtent(swapChainSupport.capabilities);

            int imageCount = swapChainSupport.capabilities.minImageCount + 1;

            if (swapChainSupport.capabilities.maxImageCount > 0 && imageCount > swapChainSupport.capabilities.maxImageCount)
            {
                imageCount = swapChainSupport.capabilities.maxImageCount;
            }

            VkSwapchainCreateInfoKHR createInfo = new VkSwapchainCreateInfoKHR();

            createInfo.sType   = VkStructureType.VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
            createInfo.surface = surface;

            createInfo.minImageCount    = imageCount;
            createInfo.imageFormat      = surfaceFormat.format;
            createInfo.imageColorSpace  = surfaceFormat.colorSpace;
            createInfo.imageExtent      = extent;
            createInfo.imageArrayLayers = 1;
            createInfo.imageUsage       = VkImageUsageFlags.VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;

            QueueFamilyIndices indices = findQueueFamilies(physicalDevice);
            var queueFamilyIndices     = new List <int>()
            {
                indices.graphicsFamily, indices.presentFamily
            };

            if (indices.graphicsFamily != indices.presentFamily)
            {
                createInfo.imageSharingMode      = VkSharingMode.VK_SHARING_MODE_CONCURRENT;
                createInfo.queueFamilyIndexCount = queueFamilyIndices.Count;
                createInfo.pQueueFamilyIndices   = queueFamilyIndices.ToArray();
            }
            else
            {
                createInfo.imageSharingMode = VkSharingMode.VK_SHARING_MODE_EXCLUSIVE;
            }

            createInfo.preTransform   = (VkSurfaceTransformFlagBitsKHR)swapChainSupport.capabilities.currentTransform;
            createInfo.compositeAlpha = VkCompositeAlphaFlagBitsKHR.VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
            createInfo.presentMode    = presentMode;
            createInfo.clipped        = VkBool32.VK_TRUE;

            createInfo.oldSwapchain = null;

            VkResult result = Vulkan.vkCreateSwapchainKHR(device, createInfo, null, out swapChain);

            if (result != VkResult.VK_SUCCESS)
            {
                throw Program.Throw("failed to create swap chain!", result);
            }

            swapChainImages = new VkImage[imageCount];
            Vulkan.vkGetSwapchainImagesKHR(device, swapChain, ref imageCount, swapChainImages);

            swapChainImageFormat = surfaceFormat.format;
            swapChainExtent      = extent;
        }
Пример #2
0
        internal VkTexture(VkGraphicsDevice gd, ref TextureDescription description)
        {
            _gd         = gd;
            _width      = description.Width;
            _height     = description.Height;
            _depth      = description.Depth;
            MipLevels   = description.MipLevels;
            ArrayLayers = description.ArrayLayers;
            bool isCubemap = ((description.Usage) & TextureUsage.Cubemap) == TextureUsage.Cubemap;

            _actualImageArrayLayers = isCubemap
                ? 6 * ArrayLayers
                : ArrayLayers;
            _format       = description.Format;
            Usage         = description.Usage;
            Type          = description.Type;
            SampleCount   = description.SampleCount;
            VkSampleCount = VkFormats.VdToVkSampleCount(SampleCount);
            VkFormat      = VkFormats.VdToVkPixelFormat(Format, (description.Usage & TextureUsage.DepthStencil) == TextureUsage.DepthStencil);

            bool isStaging = (Usage & TextureUsage.Staging) == TextureUsage.Staging;

            if (!isStaging)
            {
                VkImageCreateInfo imageCI = VkImageCreateInfo.New();
                imageCI.mipLevels     = MipLevels;
                imageCI.arrayLayers   = _actualImageArrayLayers;
                imageCI.imageType     = VkFormats.VdToVkTextureType(Type);
                imageCI.extent.width  = Width;
                imageCI.extent.height = Height;
                imageCI.extent.depth  = Depth;
                imageCI.initialLayout = VkImageLayout.Preinitialized;
                imageCI.usage         = VkFormats.VdToVkTextureUsage(Usage);
                imageCI.tiling        = isStaging ? VkImageTiling.Linear : VkImageTiling.Optimal;
                imageCI.format        = VkFormat;
                imageCI.flags         = VkImageCreateFlags.MutableFormat;

                imageCI.samples = VkSampleCount;
                if (isCubemap)
                {
                    imageCI.flags |= VkImageCreateFlags.CubeCompatible;
                }

                uint     subresourceCount = MipLevels * _actualImageArrayLayers * Depth;
                VkResult result           = vkCreateImage(gd.Device, ref imageCI, null, out _optimalImage);
                CheckResult(result);

                VkMemoryRequirements memoryRequirements;
                bool prefersDedicatedAllocation;
                if (_gd.GetImageMemoryRequirements2 != null)
                {
                    VkImageMemoryRequirementsInfo2KHR memReqsInfo2 = VkImageMemoryRequirementsInfo2KHR.New();
                    memReqsInfo2.image = _optimalImage;
                    VkMemoryRequirements2KHR         memReqs2      = VkMemoryRequirements2KHR.New();
                    VkMemoryDedicatedRequirementsKHR dedicatedReqs = VkMemoryDedicatedRequirementsKHR.New();
                    memReqs2.pNext = &dedicatedReqs;
                    _gd.GetImageMemoryRequirements2(_gd.Device, &memReqsInfo2, &memReqs2);
                    memoryRequirements         = memReqs2.memoryRequirements;
                    prefersDedicatedAllocation = dedicatedReqs.prefersDedicatedAllocation || dedicatedReqs.requiresDedicatedAllocation;
                }
                else
                {
                    vkGetImageMemoryRequirements(gd.Device, _optimalImage, out memoryRequirements);
                    prefersDedicatedAllocation = false;
                }

                VkMemoryBlock memoryToken = gd.MemoryManager.Allocate(
                    gd.PhysicalDeviceMemProperties,
                    memoryRequirements.memoryTypeBits,
                    VkMemoryPropertyFlags.DeviceLocal,
                    false,
                    memoryRequirements.size,
                    memoryRequirements.alignment,
                    prefersDedicatedAllocation,
                    _optimalImage,
                    Vulkan.VkBuffer.Null);
                _memoryBlock = memoryToken;
                result       = vkBindImageMemory(gd.Device, _optimalImage, _memoryBlock.DeviceMemory, _memoryBlock.Offset);
                CheckResult(result);

                _imageLayouts = new VkImageLayout[subresourceCount];
                for (int i = 0; i < _imageLayouts.Length; i++)
                {
                    _imageLayouts[i] = VkImageLayout.Preinitialized;
                }
            }
            else // isStaging
            {
                uint depthPitch = FormatHelpers.GetDepthPitch(
                    FormatHelpers.GetRowPitch(Width, Format),
                    Height,
                    Format);
                uint stagingSize = depthPitch * Depth;
                for (uint level = 1; level < MipLevels; level++)
                {
                    Util.GetMipDimensions(this, level, out uint mipWidth, out uint mipHeight, out uint mipDepth);

                    depthPitch = FormatHelpers.GetDepthPitch(
                        FormatHelpers.GetRowPitch(mipWidth, Format),
                        mipHeight,
                        Format);

                    stagingSize += depthPitch * mipDepth;
                }
                stagingSize *= ArrayLayers;

                VkBufferCreateInfo bufferCI = VkBufferCreateInfo.New();
                bufferCI.usage = VkBufferUsageFlags.TransferSrc | VkBufferUsageFlags.TransferDst;
                bufferCI.size  = stagingSize;
                VkResult result = vkCreateBuffer(_gd.Device, ref bufferCI, null, out _stagingBuffer);
                CheckResult(result);

                VkMemoryRequirements bufferMemReqs;
                bool prefersDedicatedAllocation;
                if (_gd.GetBufferMemoryRequirements2 != null)
                {
                    VkBufferMemoryRequirementsInfo2KHR memReqInfo2 = VkBufferMemoryRequirementsInfo2KHR.New();
                    memReqInfo2.buffer = _stagingBuffer;
                    VkMemoryRequirements2KHR         memReqs2      = VkMemoryRequirements2KHR.New();
                    VkMemoryDedicatedRequirementsKHR dedicatedReqs = VkMemoryDedicatedRequirementsKHR.New();
                    memReqs2.pNext = &dedicatedReqs;
                    _gd.GetBufferMemoryRequirements2(_gd.Device, &memReqInfo2, &memReqs2);
                    bufferMemReqs = memReqs2.memoryRequirements;
                    prefersDedicatedAllocation = dedicatedReqs.prefersDedicatedAllocation || dedicatedReqs.requiresDedicatedAllocation;
                }
                else
                {
                    vkGetBufferMemoryRequirements(gd.Device, _stagingBuffer, out bufferMemReqs);
                    prefersDedicatedAllocation = false;
                }

                _memoryBlock = _gd.MemoryManager.Allocate(
                    _gd.PhysicalDeviceMemProperties,
                    bufferMemReqs.memoryTypeBits,
                    VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent,
                    true,
                    bufferMemReqs.size,
                    bufferMemReqs.alignment,
                    prefersDedicatedAllocation,
                    VkImage.Null,
                    _stagingBuffer);

                result = vkBindBufferMemory(_gd.Device, _stagingBuffer, _memoryBlock.DeviceMemory, _memoryBlock.Offset);
                CheckResult(result);
            }

            ClearIfRenderTarget();
            TransitionIfSampled();
            RefCount = new ResourceRefCount(RefCountedDispose);
        }
Пример #3
0
        public VkFramebuffer(VkGraphicsDevice gd, ref FramebufferDescription description, bool isPresented)
            : base(description.DepthTarget, description.ColorTargets)
        {
            _gd = gd;

            VkRenderPassCreateInfo renderPassCI = VkRenderPassCreateInfo.New();

            StackList <VkAttachmentDescription> attachments = new StackList <VkAttachmentDescription>();

            uint colorAttachmentCount = (uint)ColorTargets.Count;
            StackList <VkAttachmentReference> colorAttachmentRefs = new StackList <VkAttachmentReference>();

            for (int i = 0; i < colorAttachmentCount; i++)
            {
                VkTexture vkColorTex = Util.AssertSubtype <Texture, VkTexture>(ColorTargets[i].Target);
                VkAttachmentDescription colorAttachmentDesc = new VkAttachmentDescription();
                colorAttachmentDesc.format         = vkColorTex.VkFormat;
                colorAttachmentDesc.samples        = vkColorTex.VkSampleCount;
                colorAttachmentDesc.loadOp         = VkAttachmentLoadOp.DontCare;
                colorAttachmentDesc.storeOp        = VkAttachmentStoreOp.Store;
                colorAttachmentDesc.stencilLoadOp  = VkAttachmentLoadOp.DontCare;
                colorAttachmentDesc.stencilStoreOp = VkAttachmentStoreOp.DontCare;
                colorAttachmentDesc.initialLayout  = VkImageLayout.Undefined;
                colorAttachmentDesc.finalLayout    = VkImageLayout.ColorAttachmentOptimal;
                attachments.Add(colorAttachmentDesc);

                VkAttachmentReference colorAttachmentRef = new VkAttachmentReference();
                colorAttachmentRef.attachment = (uint)i;
                colorAttachmentRef.layout     = VkImageLayout.ColorAttachmentOptimal;
                colorAttachmentRefs.Add(colorAttachmentRef);
            }

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

            if (DepthTarget != null)
            {
                VkTexture vkDepthTex = Util.AssertSubtype <Texture, VkTexture>(DepthTarget.Value.Target);
                bool      hasStencil = FormatHelpers.IsStencilFormat(vkDepthTex.Format);
                depthAttachmentDesc.format         = vkDepthTex.VkFormat;
                depthAttachmentDesc.samples        = vkDepthTex.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)description.ColorTargets.Length;
                depthAttachmentRef.layout     = VkImageLayout.DepthStencilAttachmentOptimal;
            }

            VkSubpassDescription subpass = new VkSubpassDescription();

            subpass.pipelineBindPoint = VkPipelineBindPoint.Graphics;
            if (ColorTargets.Count > 0)
            {
                subpass.colorAttachmentCount = colorAttachmentCount;
                subpass.pColorAttachments    = (VkAttachmentReference *)colorAttachmentRefs.Data;
            }

            if (DepthTarget != 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 _renderPassNoClear);

            CheckResult(creationResult);

            for (int i = 0; i < colorAttachmentCount; i++)
            {
                attachments[i].loadOp        = VkAttachmentLoadOp.Load;
                attachments[i].initialLayout = VkImageLayout.ColorAttachmentOptimal;
            }
            if (DepthTarget != null)
            {
                attachments[attachments.Count - 1].loadOp        = VkAttachmentLoadOp.Load;
                attachments[attachments.Count - 1].initialLayout = VkImageLayout.DepthStencilAttachmentOptimal;
                bool hasStencil = FormatHelpers.IsStencilFormat(DepthTarget.Value.Target.Format);
                if (hasStencil)
                {
                    attachments[attachments.Count - 1].stencilLoadOp = VkAttachmentLoadOp.Load;
                }
            }
            creationResult = vkCreateRenderPass(_gd.Device, ref renderPassCI, null, out _renderPassNoClearLoad);
            CheckResult(creationResult);


            // Load version

            if (DepthTarget != null)
            {
                attachments[attachments.Count - 1].loadOp        = VkAttachmentLoadOp.Clear;
                attachments[attachments.Count - 1].initialLayout = VkImageLayout.Undefined;
                bool hasStencil = FormatHelpers.IsStencilFormat(DepthTarget.Value.Target.Format);
                if (hasStencil)
                {
                    attachments[attachments.Count - 1].stencilLoadOp = VkAttachmentLoadOp.Clear;
                }
            }

            for (int i = 0; i < colorAttachmentCount; i++)
            {
                attachments[i].loadOp        = VkAttachmentLoadOp.Clear;
                attachments[i].initialLayout = VkImageLayout.Undefined;
            }

            creationResult = vkCreateRenderPass(_gd.Device, ref renderPassCI, null, out _renderPassClear);
            CheckResult(creationResult);

            VkFramebufferCreateInfo fbCI = VkFramebufferCreateInfo.New();
            uint fbAttachmentsCount      = (uint)description.ColorTargets.Length;

            if (description.DepthTarget != null)
            {
                fbAttachmentsCount += 1;
            }

            VkImageView *fbAttachments = stackalloc VkImageView[(int)fbAttachmentsCount];

            for (int i = 0; i < colorAttachmentCount; i++)
            {
                VkTexture             vkColorTarget = Util.AssertSubtype <Texture, VkTexture>(description.ColorTargets[i].Target);
                VkImageViewCreateInfo imageViewCI   = VkImageViewCreateInfo.New();
                imageViewCI.image            = vkColorTarget.OptimalDeviceImage;
                imageViewCI.format           = vkColorTarget.VkFormat;
                imageViewCI.viewType         = VkImageViewType.Image2D;
                imageViewCI.subresourceRange = new VkImageSubresourceRange(
                    VkImageAspectFlags.Color,
                    description.ColorTargets[i].MipLevel,
                    1,
                    description.ColorTargets[i].ArrayLayer,
                    1);
                VkImageView *dest   = (fbAttachments + i);
                VkResult     result = vkCreateImageView(_gd.Device, ref imageViewCI, null, dest);
                CheckResult(result);
                _attachmentViews.Add(*dest);
            }

            // Depth
            if (description.DepthTarget != null)
            {
                VkTexture             vkDepthTarget = Util.AssertSubtype <Texture, VkTexture>(description.DepthTarget.Value.Target);
                bool                  hasStencil    = FormatHelpers.IsStencilFormat(vkDepthTarget.Format);
                VkImageViewCreateInfo depthViewCI   = VkImageViewCreateInfo.New();
                depthViewCI.image            = vkDepthTarget.OptimalDeviceImage;
                depthViewCI.format           = vkDepthTarget.VkFormat;
                depthViewCI.viewType         = description.DepthTarget.Value.Target.ArrayLayers == 1 ? VkImageViewType.Image2D : VkImageViewType.Image2DArray;
                depthViewCI.subresourceRange = new VkImageSubresourceRange(
                    hasStencil ? VkImageAspectFlags.Depth | VkImageAspectFlags.Stencil : VkImageAspectFlags.Depth,
                    description.DepthTarget.Value.MipLevel,
                    1,
                    description.DepthTarget.Value.ArrayLayer,
                    1);
                VkImageView *dest   = (fbAttachments + (fbAttachmentsCount - 1));
                VkResult     result = vkCreateImageView(_gd.Device, ref depthViewCI, null, dest);
                CheckResult(result);
                _attachmentViews.Add(*dest);
            }

            Texture dimTex;
            uint    mipLevel;

            if (ColorTargets.Count > 0)
            {
                dimTex   = ColorTargets[0].Target;
                mipLevel = ColorTargets[0].MipLevel;
            }
            else
            {
                Debug.Assert(DepthTarget != null);
                dimTex   = DepthTarget.Value.Target;
                mipLevel = DepthTarget.Value.MipLevel;
            }

            Util.GetMipDimensions(
                dimTex,
                mipLevel,
                out uint mipWidth,
                out uint mipHeight,
                out _);

            fbCI.width  = mipWidth;
            fbCI.height = mipHeight;

            fbCI.attachmentCount = fbAttachmentsCount;
            fbCI.pAttachments    = fbAttachments;
            fbCI.layers          = 1;
            fbCI.renderPass      = _renderPassNoClear;

            creationResult = vkCreateFramebuffer(_gd.Device, ref fbCI, null, out _deviceFramebuffer);
            CheckResult(creationResult);

            if (DepthTarget != null)
            {
                AttachmentCount += 1;
            }
            AttachmentCount += (uint)ColorTargets.Count;
        }
Пример #4
0
        public VkPipeline(VkGraphicsDevice gd, ref GraphicsPipelineDescription description)
            : base(ref description)
        {
            _gd = gd;
            IsComputePipeline = false;

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

            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   = 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
            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
                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;
            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;
        }
        private VkPipeline CreateGraphicsPipeline()
        {
            // Create shader modules. Shader modules are one of the objects required to create the
            // graphics pipeline. But after the pipeline is created, we don't need these shader
            // modules anymore, so we dispose them.
            VkShaderModule vertexShader   = Content.LoadShader("Shader.vert.spv");
            VkShaderModule fragmentShader = Content.LoadShader("Shader.frag.spv");
            VkPipelineShaderStageCreateInfo *shaderStageCreateInfos = stackalloc VkPipelineShaderStageCreateInfo[2]
            {
                new VkPipelineShaderStageCreateInfo
                {
                    sType  = VkStructureType.PipelineShaderStageCreateInfo,
                    pNext  = null,
                    stage  = VkShaderStageFlags.Vertex,
                    module = vertexShader,
                    pName  = Interop.String.ToPointer("main")
                },
                new VkPipelineShaderStageCreateInfo
                {
                    sType  = VkStructureType.PipelineShaderStageCreateInfo,
                    pNext  = null,
                    stage  = VkShaderStageFlags.Fragment,
                    module = fragmentShader,
                    pName  = Interop.String.ToPointer("main")
                }
            };

            VkVertexInputBindingDescription vertexInputBindingDescription = new VkVertexInputBindingDescription
            {
                binding   = 0,
                stride    = (uint)Unsafe.SizeOf <Vertex>(),
                inputRate = VkVertexInputRate.Vertex
            };
            VkVertexInputAttributeDescription *vertexInputAttributeDescription = stackalloc VkVertexInputAttributeDescription[3]
            {
                new VkVertexInputAttributeDescription
                {
                    location = 0,
                    binding  = 0,
                    format   = VkFormat.R32G32B32A32SFloat,
                    offset   = 0
                },  // Position.
                new VkVertexInputAttributeDescription
                {
                    location = 1,
                    binding  = 0,
                    format   = VkFormat.R32G32B32SFloat,
                    offset   = 12
                }, // Normal.
                new VkVertexInputAttributeDescription
                {
                    location = 2,
                    binding  = 0,
                    format   = VkFormat.R32G32SFloat,
                    offset   = 24
                }// TexCoord.
            };
            var vertexInputStateCreateInfo = new VkPipelineVertexInputStateCreateInfo
            {
                sType = VkStructureType.PipelineVertexInputStateCreateInfo,
                pNext = null,
                vertexBindingDescriptionCount   = 1,
                pVertexBindingDescriptions      = &vertexInputBindingDescription,
                vertexAttributeDescriptionCount = 3,
                pVertexAttributeDescriptions    = vertexInputAttributeDescription
            };
            var inputAssemblyStateCreateInfo = new VkPipelineInputAssemblyStateCreateInfo
            {
                sType    = VkStructureType.PipelineInputAssemblyStateCreateInfo,
                pNext    = null,
                topology = VkPrimitiveTopology.TriangleList
            };

            Viewport  viewport = new Viewport(0, 0, Host.Width, Host.Height);
            Rectangle scissor  = new Rectangle(0, 0, Host.Width, Host.Height);

            var viewportStateCreateInfo = new VkPipelineViewportStateCreateInfo
            {
                sType         = VkStructureType.PipelineViewportStateCreateInfo,
                pNext         = null,
                viewportCount = 1,
                pViewports    = &viewport,
                scissorCount  = 1,
                pScissors     = &scissor
            };
            var rasterizationStateCreateInfo = new VkPipelineRasterizationStateCreateInfo
            {
                sType       = VkStructureType.PipelineRasterizationStateCreateInfo,
                polygonMode = VkPolygonMode.Fill,
                cullMode    = VkCullModeFlags.Back,
                frontFace   = VkFrontFace.CounterClockwise,
                lineWidth   = 1.0f
            };
            var multisampleStateCreateInfo = new VkPipelineMultisampleStateCreateInfo
            {
                sType = VkStructureType.PipelineMultisampleStateCreateInfo,
                rasterizationSamples = VkSampleCountFlags.Count1,
                minSampleShading     = 1.0f
            };
            var depthStencilStateCreateInfo = new VkPipelineDepthStencilStateCreateInfo
            {
                sType            = VkStructureType.PipelineDepthStencilStateCreateInfo,
                depthTestEnable  = true,
                depthWriteEnable = true,
                depthCompareOp   = VkCompareOp.LessOrEqual,
                back             = new VkStencilOpState
                {
                    failOp    = VkStencilOp.Keep,
                    passOp    = VkStencilOp.Keep,
                    compareOp = VkCompareOp.Always
                },
                front = new VkStencilOpState
                {
                    failOp    = VkStencilOp.Keep,
                    passOp    = VkStencilOp.Keep,
                    compareOp = VkCompareOp.Always
                }
            };
            var colorBlendAttachmentState = new VkPipelineColorBlendAttachmentState
            {
                srcColorBlendFactor = VkBlendFactor.One,
                dstColorBlendFactor = VkBlendFactor.Zero,
                colorBlendOp        = VkBlendOp.Add,
                srcAlphaBlendFactor = VkBlendFactor.One,
                dstAlphaBlendFactor = VkBlendFactor.Zero,
                alphaBlendOp        = VkBlendOp.Add,
                colorWriteMask      = VkColorComponentFlags.All
            };
            var colorBlendStateCreateInfo = new VkPipelineColorBlendStateCreateInfo
            {
                sType           = VkStructureType.PipelineColorBlendStateCreateInfo,
                pNext           = null,
                attachmentCount = 1,
                pAttachments    = &colorBlendAttachmentState
            };

            var pipelineCreateInfo = new VkGraphicsPipelineCreateInfo
            {
                sType               = VkStructureType.GraphicsPipelineCreateInfo,
                pNext               = null,
                layout              = _pipelineLayout,
                renderPass          = _renderPass,
                subpass             = (uint)0,
                stageCount          = 2,
                pStages             = shaderStageCreateInfos,
                pInputAssemblyState = &inputAssemblyStateCreateInfo,
                pVertexInputState   = &vertexInputStateCreateInfo,
                pRasterizationState = &rasterizationStateCreateInfo,
                pMultisampleState   = &multisampleStateCreateInfo,
                pColorBlendState    = &colorBlendStateCreateInfo,
                pDepthStencilState  = &depthStencilStateCreateInfo,
                pViewportState      = &viewportStateCreateInfo
            };


            VkPipeline pipeline;
            VkResult   result = vkCreateGraphicsPipelines(Context.Device, VkPipelineCache.Null, 1, &pipelineCreateInfo, null, &pipeline);

            result.CheckResult();

            return(pipeline);
        }
    }
}
Пример #6
0
        private SoftwareImage(SoftwareDevice device, VkSwapchainCreateInfoKHR createInfo, out VkResult result)
        {
            this.m_device = device;

            this.m_imageFormat     = createInfo.imageFormat;
            this.m_imageExtent     = VkExtent3D.Create(createInfo.imageExtent.width, createInfo.imageExtent.height, 1);
            this.m_imageColorSpace = createInfo.imageColorSpace;

            Initialize(out result);
        }
Пример #7
0
        private SoftwareImage(SoftwareDevice device, VkFormat format, VkExtent3D imageExtent, VkColorSpaceKHR colorSpace, out VkResult result)
        {
            this.m_device          = device;
            this.m_imageFormat     = format;
            this.m_imageExtent     = imageExtent;
            this.m_imageColorSpace = colorSpace;

            Initialize(out result);
        }
Пример #8
0
        public static SoftwareImage CreateSwapchainImage(SoftwareDevice device, VkSwapchainCreateInfoKHR swapchainInfo, out VkResult result)
        {
            VkImageCreateInfo createInfo = new VkImageCreateInfo();

            createInfo.extent        = VkExtent3D.Create(swapchainInfo.imageExtent.width, swapchainInfo.imageExtent.height, 1);
            createInfo.format        = swapchainInfo.imageFormat;
            createInfo.imageType     = VkImageType.VK_IMAGE_TYPE_2D;
            createInfo.arrayLayers   = swapchainInfo.imageArrayLayers;
            createInfo.sharingMode   = swapchainInfo.imageSharingMode;
            createInfo.usage         = VkImageUsageFlags.VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VkImageUsageFlags.VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
            createInfo.samples       = VkSampleCountFlagBits.VK_SAMPLE_COUNT_1_BIT;
            createInfo.mipLevels     = 1;
            createInfo.initialLayout = VkImageLayout.VK_IMAGE_LAYOUT_UNDEFINED;

            return(new SoftwareImage(device, createInfo, out result));
        }
Пример #9
0
 public static SoftwareImage CreateImage(SoftwareDevice device, VkImageCreateInfo createInfo, out VkResult result)
 {
     return(new SoftwareImage(device, createInfo, out result));
 }
Пример #10
0
        public void InitVulkan()
        {
            VkResult err;

            err = CreateInstance(true);
            if (err != VkResult.Success)
            {
                throw new InvalidOperationException("Could not create Vulkan instance.");
            }

            if (Settings.Validation)
            {
            }

            // Physical Device
            uint gpuCount = 0;

            Util.CheckResult(vkEnumeratePhysicalDevices(Instance, &gpuCount, null));
            Debug.Assert(gpuCount > 0);
            // Enumerate devices
            IntPtr *physicalDevices = stackalloc IntPtr[(int)gpuCount];

            err = vkEnumeratePhysicalDevices(Instance, &gpuCount, (VkPhysicalDevice *)physicalDevices);
            if (err != VkResult.Success)
            {
                throw new InvalidOperationException("Could not enumerate physical devices.");
            }

            // GPU selection

            // Select physical Device to be used for the Vulkan example
            // Defaults to the first Device unless specified by command line

            uint selectedDevice = 0;

            // TODO: Implement arg parsing, etc.

            PhysicalDevice = ((VkPhysicalDevice *)physicalDevices)[selectedDevice];

            // Store properties (including limits) and features of the phyiscal Device
            // So examples can check against them and see if a feature is actually supported
            VkPhysicalDeviceProperties deviceProperties;

            vkGetPhysicalDeviceProperties(PhysicalDevice, &deviceProperties);
            DeviceProperties = deviceProperties;

            VkPhysicalDeviceFeatures deviceFeatures;

            vkGetPhysicalDeviceFeatures(PhysicalDevice, &deviceFeatures);
            DeviceFeatures = deviceFeatures;

            // Gather physical Device memory properties
            VkPhysicalDeviceMemoryProperties deviceMemoryProperties;

            vkGetPhysicalDeviceMemoryProperties(PhysicalDevice, &deviceMemoryProperties);
            DeviceMemoryProperties = deviceMemoryProperties;

            // Derived examples can override this to set actual features (based on above readings) to enable for logical device creation
            getEnabledFeatures();

            // Vulkan Device creation
            // This is handled by a separate class that gets a logical Device representation
            // and encapsulates functions related to a Device
            VulkanDevice = new vksVulkanDevice(PhysicalDevice);
            VkResult res = VulkanDevice.CreateLogicalDevice(EnabledFeatures, EnabledExtensions);

            if (res != VkResult.Success)
            {
                throw new InvalidOperationException("Could not create Vulkan Device.");
            }
            Device = VulkanDevice.LogicalDevice;

            // Get a graphics queue from the Device
            VkQueue queue;

            vkGetDeviceQueue(Device, VulkanDevice.QFIndices.Graphics, 0, &queue);
            Queue = queue;

            // Find a suitable depth format
            VkFormat depthFormat;
            uint     validDepthFormat = Tools.getSupportedDepthFormat(PhysicalDevice, &depthFormat);

            Debug.Assert(validDepthFormat == True);
            DepthFormat = depthFormat;

            Swapchain.Connect(Instance, PhysicalDevice, Device);

            // Create synchronization objects
            VkSemaphoreCreateInfo semaphoreCreateInfo = Initializers.SemaphoreCreateInfo();

            // Create a semaphore used to synchronize image presentation
            // Ensures that the image is displayed before we start submitting new commands to the queu
            Util.CheckResult(vkCreateSemaphore(Device, &semaphoreCreateInfo, null, &GetSemaphoresPtr()->PresentComplete));
            // Create a semaphore used to synchronize command submission
            // Ensures that the image is not presented until all commands have been sumbitted and executed
            Util.CheckResult(vkCreateSemaphore(Device, &semaphoreCreateInfo, null, &GetSemaphoresPtr()->RenderComplete));
            // Create a semaphore used to synchronize command submission
            // Ensures that the image is not presented until all commands for the text overlay have been sumbitted and executed
            // Will be inserted after the render complete semaphore if the text overlay is enabled
            Util.CheckResult(vkCreateSemaphore(Device, &semaphoreCreateInfo, null, &GetSemaphoresPtr()->TextOverlayComplete));

            // Set up submit info structure
            // Semaphores will stay the same during application lifetime
            // Command buffer submission info is set by each example
            SubmitInfo = Initializers.SubmitInfo();
            SubmitInfo.pWaitDstStageMask    = (VkPipelineStageFlags *)submitPipelineStages.Data;
            SubmitInfo.waitSemaphoreCount   = 1;
            SubmitInfo.pWaitSemaphores      = &GetSemaphoresPtr()->PresentComplete;
            SubmitInfo.signalSemaphoreCount = 1;
            SubmitInfo.pSignalSemaphores    = &GetSemaphoresPtr()->RenderComplete;
        }
Пример #11
0
        public VkResourceLayout(VkGraphicsDevice gd, ref ResourceLayoutDescription description)
            : base(ref description)
        {
            _gd = gd;
            VkDescriptorSetLayoutCreateInfo dslCI = VkDescriptorSetLayoutCreateInfo.New();

            ResourceLayoutElementDescription[] elements = description.Elements;
            _descriptorTypes = new VkDescriptorType[elements.Length];
            VkDescriptorSetLayoutBinding *bindings = stackalloc VkDescriptorSetLayoutBinding[elements.Length];

            uint uniformBufferCount = 0;
            uint sampledImageCount  = 0;
            uint samplerCount       = 0;
            uint storageBufferCount = 0;
            uint storageImageCount  = 0;

            for (uint i = 0; i < elements.Length; i++)
            {
                bindings[i].binding         = i;
                bindings[i].descriptorCount = 1;
                VkDescriptorType descriptorType = VkFormats.VdToVkDescriptorType(elements[i].Kind, elements[i].Options);
                bindings[i].descriptorType = descriptorType;
                bindings[i].stageFlags     = VkFormats.VdToVkShaderStages(elements[i].Stages);
                if ((elements[i].Options & ResourceLayoutElementOptions.DynamicBinding) != 0)
                {
                    DynamicBufferCount += 1;
                }

                _descriptorTypes[i] = descriptorType;

                switch (descriptorType)
                {
                case VkDescriptorType.Sampler:
                    samplerCount += 1;
                    break;

                case VkDescriptorType.SampledImage:
                    sampledImageCount += 1;
                    break;

                case VkDescriptorType.StorageImage:
                    storageImageCount += 1;
                    break;

                case VkDescriptorType.UniformBuffer:
                    uniformBufferCount += 1;
                    break;

                case VkDescriptorType.StorageBuffer:
                    storageBufferCount += 1;
                    break;
                }
            }

            DescriptorResourceCounts = new DescriptorResourceCounts(
                uniformBufferCount,
                sampledImageCount,
                samplerCount,
                storageBufferCount,
                storageImageCount);

            dslCI.bindingCount = (uint)elements.Length;
            dslCI.pBindings    = bindings;

            VkResult result = vkCreateDescriptorSetLayout(_gd.Device, ref dslCI, null, out _dsl);

            CheckResult(result);
        }
Пример #12
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;
            }
        }
Пример #13
0
        private void RecordCommandBuffers()
        {
            VkImageSubresourceRange subresourceRange = new VkImageSubresourceRange()
            {
                aspectMask     = VkImageAspectFlags.Color,
                baseMipLevel   = 0,
                baseArrayLayer = 0,
                layerCount     = 1,
                levelCount     = 1
            };

            for (int i = 0; i < CommandBuffers.Length; i++)
            {
                VkCommandBuffer cmdBuffer = CommandBuffers[i];

                VkCommandBufferBeginInfo beginInfo = new VkCommandBufferBeginInfo()
                {
                    sType = VkStructureType.CommandBufferBeginInfo,
                    flags = VkCommandBufferUsageFlags.SimultaneousUse
                };
                vkBeginCommandBuffer(cmdBuffer, &beginInfo);

                if (Context.PresentQueue != Context.GraphicsQueue)
                {
                    var barrierFromPresentToDraw = new VkImageMemoryBarrier(
                        SwapchainImages[i], subresourceRange,
                        VkAccessFlags.MemoryRead, VkAccessFlags.ColorAttachmentWrite,
                        VkImageLayout.Undefined, VkImageLayout.PresentSrcKHR,
                        (uint)Context.PresentQueueFamilyIndex, (uint)Context.GraphicsQueueFamilyIndex);

                    vkCmdPipelineBarrier(cmdBuffer,
                                         VkPipelineStageFlags.ColorAttachmentOutput,
                                         VkPipelineStageFlags.ColorAttachmentOutput,
                                         0,
                                         0, null, 0, null,
                                         1, &barrierFromPresentToDraw
                                         );
                }

                RecordCommandBuffer(cmdBuffer, i);

                if (Context.PresentQueue != Context.GraphicsQueue)
                {
                    var barrierFromDrawToPresent = new VkImageMemoryBarrier(
                        SwapchainImages[i], subresourceRange,
                        VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.MemoryRead,
                        VkImageLayout.PresentSrcKHR, VkImageLayout.PresentSrcKHR,
                        (uint)Context.GraphicsQueueFamilyIndex, (uint)Context.PresentQueueFamilyIndex);

                    vkCmdPipelineBarrier(cmdBuffer,
                                         VkPipelineStageFlags.ColorAttachmentOutput,
                                         VkPipelineStageFlags.BottomOfPipe,
                                         0,
                                         0, null, 0, null,
                                         1, &barrierFromDrawToPresent
                                         );
                }

                VkResult result = vkEndCommandBuffer(cmdBuffer);
                result.CheckResult();
            }
        }
Пример #14
0
        private VkInstance CreateInstance(bool debug)
        {
            VkInstance instance;

            // Specify standard validation layers.
            string surfaceExtension;

            switch (Host.Platform)
            {
            case Platform.Android:
                surfaceExtension = KHRAndroidSurfaceExtensionName;
                break;

            case Platform.Win32:
                surfaceExtension = KHRWin32SurfaceExtensionName;
                break;

            default:
                throw new NotImplementedException();
            }

            VkString name    = "TODO Application Name";
            var      appInfo = new VkApplicationInfo
            {
                sType              = VkStructureType.ApplicationInfo,
                pApplicationName   = name,
                applicationVersion = new VkVersion(1, 0, 0),
                pEngineName        = s_EngineName,
                engineVersion      = new VkVersion(1, 0, 0),
                apiVersion         = VkVersion.Version_1_0,
            };

            var instanceExtensions = new List <string>
            {
                KHRSurfaceExtensionName,
                surfaceExtension
            };

            var instanceLayers = new List <string>();

            if (EnableValidationLayers)
            {
                FindValidationLayers(instanceLayers);
            }

            if (instanceLayers.Count > 0)
            {
                instanceExtensions.Add(EXTDebugUtilsExtensionName);
            }

            using var vkInstanceExtensions = new VkStringArray(instanceExtensions);
            var instanceCreateInfo = new VkInstanceCreateInfo
            {
                sType                   = VkStructureType.InstanceCreateInfo,
                pApplicationInfo        = &appInfo,
                enabledExtensionCount   = vkInstanceExtensions.Length,
                ppEnabledExtensionNames = vkInstanceExtensions
            };


            using var vkLayerNames = new VkStringArray(instanceLayers);
            if (instanceLayers.Count > 0)
            {
                instanceCreateInfo.enabledLayerCount   = vkLayerNames.Length;
                instanceCreateInfo.ppEnabledLayerNames = vkLayerNames;
            }

            VkResult result = vkCreateInstance(&instanceCreateInfo, null, out instance);

            vkLoadInstance(instance);

            if (instanceLayers.Count > 0)
            {
                _debugMessengerCallbackFunc = DebugMessengerCallback;
                var debugCreateInfo = new VkDebugUtilsMessengerCreateInfoEXT
                {
                    sType           = VkStructureType.DebugUtilsMessengerCreateInfoEXT,
                    messageSeverity = VkDebugUtilsMessageSeverityFlagsEXT.Verbose | VkDebugUtilsMessageSeverityFlagsEXT.Error | VkDebugUtilsMessageSeverityFlagsEXT.Warning,
                    messageType     = VkDebugUtilsMessageTypeFlagsEXT.General | VkDebugUtilsMessageTypeFlagsEXT.Validation | VkDebugUtilsMessageTypeFlagsEXT.Performance,
                    pfnUserCallback = Marshal.GetFunctionPointerForDelegate(_debugMessengerCallbackFunc)
                };

                vkCreateDebugUtilsMessengerEXT(instance, &debugCreateInfo, null, out debugMessenger).CheckResult();
            }

            return(instance);
        }
Пример #15
0
        public void Initialize(IVulkanAppHost host)
        {
            Host = host;
#if DEBUG
            const bool debug = true;
#else
            const bool debug = false;
#endif
            _initializingPermanent = true;

            VkResult result = vkInitialize();
            result.CheckResult();

            // Calling ToDispose here registers the resource to be automatically disposed on exit.
            Instance = CreateInstance(debug);
            Surface  = CreateSurface();
            Context  = new VulkanContext(Instance, Surface, Host.Platform);
            Content  = new ContentManager(Host, Context, "Content");
            ImageAvailableSemaphore    = CreateSemaphore(Context.Device);
            RenderingFinishedSemaphore = CreateSemaphore(Context.Device);

            _initializingPermanent = false;
            // Calling ToDispose here registers the resource to be automatically disposed on events
            // such as window resize.
            var swapchain = CreateSwapchain();
            Swapchain = swapchain;
            ToDispose(new ActionDisposable(() =>
            {
                vkDestroySwapchainKHR(Context.Device, swapchain, null);
            }));

            // Acquire underlying images of the freshly created swapchain.
            uint swapchainImageCount;
            result = vkGetSwapchainImagesKHR(Context.Device, Swapchain, &swapchainImageCount, null);
            result.CheckResult();

            var swapchainImages = stackalloc VkImage[(int)swapchainImageCount];
            result = vkGetSwapchainImagesKHR(Context.Device, Swapchain, &swapchainImageCount, swapchainImages);
            result.CheckResult();

            SwapchainImages = new VkImage[swapchainImageCount];
            for (int i = 0; i < swapchainImageCount; i++)
            {
                SwapchainImages[i] = swapchainImages[i];
            }

            VkCommandBufferAllocateInfo allocInfo = new VkCommandBufferAllocateInfo()
            {
                sType       = VkStructureType.CommandBufferAllocateInfo,
                commandPool = Context.GraphicsCommandPool,

                level = VkCommandBufferLevel.Primary,
                commandBufferCount = (uint)SwapchainImages.Length,
            };

            VkCommandBuffer[] commandBuffers = new VkCommandBuffer[SwapchainImages.Length];
            fixed(VkCommandBuffer *commandBuffersPtr = &commandBuffers[0])
            {
                vkAllocateCommandBuffers(Context.Device, &allocInfo, commandBuffersPtr).CheckResult();
            }

            CommandBuffers = commandBuffers;

            // Create a fence for each commandbuffer so that we can wait before using it again
            _initializingPermanent = true; //We need our fences to be there permanently
            SubmitFences           = new VkFence[SwapchainImages.Length];
            for (int i = 0; i < SubmitFences.Length; i++)
            {
                VkFenceCreateInfo fenceCreateInfo = new VkFenceCreateInfo()
                {
                    sType = VkStructureType.FenceCreateInfo,
                    pNext = null,
                    flags = VkFenceCreateFlags.Signaled
                };

                VkFence handle;

                vkCreateFence(Context.Device, &fenceCreateInfo, null, out handle);

                SubmitFences[i] = handle;
                ToDispose(new ActionDisposable(() =>
                {
                    vkDestroyFence(Context.Device, handle, null);
                }));
            }

            // Allow concrete samples to initialize their resources.
            InitializePermanent();
            _initializingPermanent = false;
            InitializeFrame();

            // Record commands for execution by Vulkan.
            RecordCommandBuffers();
        }
Пример #16
0
        public VkResult CreateLogicalDevice(
            VkPhysicalDeviceFeatures enabledFeatures,
            string[] enabledExtensions,
            bool useSwapChain = true,
            VkQueueFlagBits requestedQueueTypes = VkQueueFlagBits.Graphics | VkQueueFlagBits.Compute)
        {
            // Desired queues need to be requested upon logical device creation
            // Due to differing queue family configurations of Vulkan implementations this can be a bit tricky, especially if the application
            // requests different queue types

            var   queueCreateInfos     = new List <VkDeviceQueueCreateInfo>();
            float defaultQueuePriority = 0.0f;

            // Graphics queue
            if ((requestedQueueTypes & VkQueueFlagBits.Graphics) != 0)
            {
                QFIndices.Graphics = GetQueueFamilyIndex(VkQueueFlagBits.Graphics);
                VkDeviceQueueCreateInfo queueInfo = new VkDeviceQueueCreateInfo();
                queueInfo.sType            = DeviceQueueCreateInfo;
                queueInfo.queueFamilyIndex = QFIndices.Graphics;
                queueInfo.queuePriorities  = defaultQueuePriority;
                queueCreateInfos.Add(queueInfo);
            }
            else
            {
                QFIndices.Graphics = 0;
            }

            // Dedicated compute queue
            if ((requestedQueueTypes & VkQueueFlagBits.Compute) != 0)
            {
                QFIndices.Compute = GetQueueFamilyIndex(VkQueueFlagBits.Compute);
                if (QFIndices.Compute != QFIndices.Graphics)
                {
                    // If compute family index differs, we need an additional queue create info for the compute queue
                    VkDeviceQueueCreateInfo queueInfo = new VkDeviceQueueCreateInfo();
                    queueInfo.sType            = DeviceQueueCreateInfo;
                    queueInfo.queueFamilyIndex = QFIndices.Compute;
                    queueInfo.queuePriorities  = defaultQueuePriority;
                    queueCreateInfos.Add(queueInfo);
                }
            }
            else
            {
                // Else we use the same queue
                QFIndices.Compute = QFIndices.Graphics;
            }

            // Dedicated transfer queue
            if ((requestedQueueTypes & VkQueueFlagBits.Transfer) != 0)
            {
                QFIndices.Transfer = GetQueueFamilyIndex(VkQueueFlagBits.Transfer);
                if (QFIndices.Transfer != QFIndices.Graphics && QFIndices.Transfer != QFIndices.Compute)
                {
                    // If compute family index differs, we need an additional queue create info for the transfer queue
                    VkDeviceQueueCreateInfo queueInfo = new VkDeviceQueueCreateInfo();
                    queueInfo.sType            = DeviceQueueCreateInfo;
                    queueInfo.queueFamilyIndex = QFIndices.Transfer;
                    queueInfo.queuePriorities  = defaultQueuePriority;
                    queueCreateInfos.Add(queueInfo);
                }
            }
            else
            {
                // Else we use the same queue
                QFIndices.Transfer = QFIndices.Graphics;
            }

            // Create the logical device representation
            //using (NativeList<IntPtr> deviceExtensions = new NativeList<IntPtr>(enabledExtensions)) {
            var deviceExtensions = new List <string>();

            if (useSwapChain)
            {
                // If the device will be used for presenting to a display via a swapchain we need to request the swapchain extension
                deviceExtensions.Add(Strings.VK_KHR_SWAPCHAIN_EXTENSION_NAME);
            }

            var deviceCreateInfo = VkDeviceCreateInfo.Alloc();

            //deviceCreateInfo.queueCreateInfoCount = (uint)queueCreateInfos.Count;
            //deviceCreateInfo.pQueueCreateInfos = (VkDeviceQueueCreateInfo*)queueCreateInfos.Data.ToPointer();
            //{
            //    VkDeviceQueueCreateInfo[] array = queueCreateInfos.ToArray();
            //    IntPtr ptr = IntPtr.Zero;
            //    array.Set(ref ptr, ref deviceCreateInfo.queueCreateInfoCount);
            //    deviceCreateInfo.pQueueCreateInfos = (VkDeviceQueueCreateInfo*)ptr;
            //}
            deviceCreateInfo->queueCreateInfos = queueCreateInfos.ToArray();
            deviceCreateInfo->pEnabledFeatures = &enabledFeatures;

            if (deviceExtensions.Count > 0)
            {
                string[] array = deviceExtensions.ToArray();
                deviceCreateInfo[0].EnabledExtensions = array;
            }

            VkDevice device;
            VkResult result = vkCreateDevice(PhysicalDevice, deviceCreateInfo, null, &device);

            this._logicalDevice = device;
            if (result == VkResult.Success)
            {
                // Create a default command pool for graphics command buffers
                CommandPool = CreateCommandPool(QFIndices.Graphics);
            }

            return(result);
        }