// Used to construct Swapchain textures. internal VkTexture( VkGraphicsDevice gd, uint width, uint height, uint mipLevels, uint arrayLayers, VkFormat vkFormat, TextureUsage usage, TextureSampleCount sampleCount, VkImage existingImage) { Debug.Assert(width > 0 && height > 0); _gd = gd; MipLevels = mipLevels; _width = width; _height = height; _depth = 1; VkFormat = vkFormat; _format = VkFormats.VkToVdPixelFormat(VkFormat); ArrayLayers = arrayLayers; Usage = usage; Type = TextureType.Texture2D; SampleCount = sampleCount; VkSampleCount = VkFormats.VdToVkSampleCount(sampleCount); _optimalImage = existingImage; _imageLayouts = new[] { VkImageLayout.Undefined }; ClearIfRenderTarget(); }
public DebugDrawPipeline(RenderPass renderPass, uint maxVertices = 100, VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1, PipelineCache pipelineCache = null) : base(renderPass, pipelineCache, "Debug draw pipeline") { vboLength = maxVertices * 6 * sizeof(float); using (GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault(VkPrimitiveTopology.LineList, samples, false)) { cfg.rasterizationState.lineWidth = 1.0f; cfg.RenderPass = RenderPass; cfg.Layout = new PipelineLayout(Dev, new VkPushConstantRange(VkShaderStageFlags.Vertex, (uint)Marshal.SizeOf <Matrix4x4> () * 2)); cfg.AddVertexBinding(0, 6 * sizeof(float)); cfg.AddVertexAttributes(0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32b32Sfloat); cfg.blendAttachments[0] = new VkPipelineColorBlendAttachmentState(true); cfg.AddShaders( new ShaderInfo(Dev, VkShaderStageFlags.Vertex, "#vke.debug.vert.spv"), new ShaderInfo(Dev, VkShaderStageFlags.Fragment, "#vke.debug.frag.spv") ); layout = cfg.Layout; init(cfg); } Vertices = new HostBuffer(Dev, VkBufferUsageFlags.VertexBuffer, vboLength); Vertices.Map(); }
void init(VkSampleCountFlags samples = VkSampleCountFlags.SampleCount4) { descriptorPool = new DescriptorPool(dev, 2, new VkDescriptorPoolSize(VkDescriptorType.CombinedImageSampler) ); descLayout = new DescriptorSetLayout(dev, new VkDescriptorSetLayoutBinding(0, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler) ); GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault(VkPrimitiveTopology.TriangleList, samples); cfg.Layout = new PipelineLayout(dev, descLayout); cfg.RenderPass = new RenderPass(dev, swapChain.ColorFormat, dev.GetSuitableDepthFormat(), samples); cfg.ResetShadersAndVerticesInfos(); cfg.AddShader(VkShaderStageFlags.Vertex, "shaders/FullScreenQuad.vert.spv"); cfg.AddShader(VkShaderStageFlags.Fragment, "shaders/simpletexture.frag.spv"); cfg.blendAttachments[0] = new VkPipelineColorBlendAttachmentState(true); uiPipeline = new GraphicPipeline(cfg); dsVkvg = descriptorPool.Allocate(descLayout); }
/// <summary> /// Create renderpass with a single color attachment and a resolve one if needed /// </summary> public RenderPass(Device device, VkFormat colorFormat, VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1) : this(device) { Samples = samples; AddAttachment(colorFormat, (samples == VkSampleCountFlags.SampleCount1) ? VkImageLayout.PresentSrcKHR : VkImageLayout.ColorAttachmentOptimal, samples, VkAttachmentLoadOp.Load, VkAttachmentStoreOp.Store, VkImageLayout.ColorAttachmentOptimal); ClearValues.Add(new VkClearValue { color = new VkClearColorValue(0.0f, 0.0f, 0.0f) }); SubPass subpass0 = new SubPass(); subpass0.AddColorReference(0, VkImageLayout.ColorAttachmentOptimal); if (samples != VkSampleCountFlags.SampleCount1) { AddAttachment(colorFormat, VkImageLayout.PresentSrcKHR, VkSampleCountFlags.SampleCount1); ClearValues.Add(new VkClearValue { color = new VkClearColorValue(0.0f, 0.0f, 0.0f) }); subpass0.AddResolveReference(1, VkImageLayout.ColorAttachmentOptimal); } AddSubpass(subpass0); AddDependency(Vk.SubpassExternal, 0, VkPipelineStageFlags.BottomOfPipe, VkPipelineStageFlags.ColorAttachmentOutput, VkAccessFlags.MemoryRead, VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite); AddDependency(0, Vk.SubpassExternal, VkPipelineStageFlags.ColorAttachmentOutput, VkPipelineStageFlags.BottomOfPipe, VkAccessFlags.ColorAttachmentRead | VkAccessFlags.ColorAttachmentWrite, VkAccessFlags.MemoryRead); }
private (VkAttachmentDescription, VkAttachmentReference) CreateAttachment( VkFormat format, VkSampleCountFlags samples, uint index, VkAttachmentLoadOp loadOp, VkAttachmentStoreOp storeOp, VkAttachmentStoreOp stencilStoreOp, VkImageLayout initialLayout, VkImageLayout finalLayout) { return(new VkAttachmentDescription() { format = format, samples = samples, loadOp = loadOp, storeOp = storeOp, stencilLoadOp = VkAttachmentLoadOp.Load, stencilStoreOp = stencilStoreOp, initialLayout = initialLayout, finalLayout = finalLayout }, new VkAttachmentReference() { attachment = index, layout = finalLayout }); }
/// <summary> /// Create a new Image. /// </summary> /// <remarks>Initial layout will be automatically set to Undefined if tiling is optimal and Preinitialized if tiling is linear.</remarks> /// <param name="device">The logical device that create the image.</param> /// <param name="format">format and type of the texel blocks that will be contained in the image</param> /// <param name="usage">bitmask describing the intended usage of the image.</param> /// <param name="_memoryPropertyFlags">Memory property flags.</param> /// <param name="width">number of data in the X dimension of the image.</param> /// <param name="height">number of data in the Y dimension of the image.</param> /// <param name="type">value specifying the basic dimensionality of the image. Layers in array textures do not count as a dimension for the purposes of the image type.</param> /// <param name="samples">number of sample per texel.</param> /// <param name="tiling">tiling arrangement of the texel blocks in memory.</param> /// <param name="mipsLevels">describes the number of levels of detail available for minified sampling of the image.</param> /// <param name="layers">number of layers in the image.</param> /// <param name="depth">number of data in the Z dimension of the image</param> /// <param name="createFlags">bitmask describing additional parameters of the image.</param> /// <param name="sharingMode">value specifying the sharing mode of the image when it will be accessed by multiple queue families.</param> /// <param name="queuesFamillies">list of queue families that will access this image (ignored if sharingMode is not CONCURRENT).</param> public Image(Device device, VkFormat format, VkImageUsageFlags usage, VkMemoryPropertyFlags _memoryPropertyFlags, uint width, uint height, VkImageType type = VkImageType.Image2D, VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1, VkImageTiling tiling = VkImageTiling.Optimal, uint mipsLevels = 1, uint layers = 1, uint depth = 1, VkImageCreateFlags createFlags = 0, VkSharingMode sharingMode = VkSharingMode.Exclusive, params uint[] queuesFamillies) : base(device, _memoryPropertyFlags) { info.imageType = type; info.format = format; info.extent.width = width; info.extent.height = height; info.extent.depth = depth; info.mipLevels = mipsLevels; info.arrayLayers = layers; info.samples = samples; info.tiling = tiling; info.usage = usage; info.initialLayout = (tiling == VkImageTiling.Optimal) ? VkImageLayout.Undefined : VkImageLayout.Preinitialized; info.sharingMode = sharingMode; info.flags = createFlags; this.queueFalillies = queuesFamillies; lastKnownLayout = info.initialLayout; Activate(); }
public static VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo( VkSampleCountFlags rasterizationSamples, uint flags = 0) { VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo = VkPipelineMultisampleStateCreateInfo.New(); pipelineMultisampleStateCreateInfo.rasterizationSamples = rasterizationSamples; pipelineMultisampleStateCreateInfo.flags = flags; return(pipelineMultisampleStateCreateInfo); }
public static extern void GetPhysicalDeviceSparseImageFormatProperties( VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlags samples, VkImageUsageFlags usage, VkImageTiling tiling, ref uint pPropertyCount, IntPtr pProperties );
public RenderTexture(uint width, uint height, uint layers, VkFormat format, VkImageUsageFlags usage, VkSampleCountFlags samples = VkSampleCountFlags.Count1, SizeHint sizeHint = SizeHint.None) { this.extent = new VkExtent3D(width, height, 1); this.layers = layers; this.format = format; this.imageUsageFlags = usage; this.samples = samples; this.sizeHint = sizeHint; Create(); }
public void AddAttachment(VkFormat format, VkImageLayout finalLayout, VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1, VkAttachmentLoadOp loadOp = VkAttachmentLoadOp.Clear, VkAttachmentStoreOp storeOp = VkAttachmentStoreOp.Store, VkImageLayout initialLayout = VkImageLayout.Undefined) { attachments.Add(new VkAttachmentDescription { format = format, samples = samples, loadOp = loadOp, storeOp = storeOp, stencilLoadOp = VkAttachmentLoadOp.DontCare, stencilStoreOp = VkAttachmentStoreOp.DontCare, initialLayout = initialLayout, finalLayout = finalLayout, }); }
/// <summary> /// Create a default pipeline configuration with viewport and scissor as dynamic states. One blend attachment is /// added automatically with blending disabled. (cfg.blendAttachments[0]) /// If width and height parameter are omitted viewport and scissor dynamic states are automatically added, else /// a viewport and a vkrect2d are added to the viewport and scissor lists. /// </summary> public static GraphicPipelineConfig CreateDefault(VkPrimitiveTopology topology = VkPrimitiveTopology.TriangleList, VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1, bool depthTestEnabled = true, int width = -1, int height = -1) { GraphicPipelineConfig cfg = new GraphicPipelineConfig(); cfg.inputAssemblyState.topology = topology; cfg.multisampleState.rasterizationSamples = samples; cfg.rasterizationState.polygonMode = VkPolygonMode.Fill; cfg.rasterizationState.cullMode = (uint)VkCullModeFlags.None; cfg.rasterizationState.frontFace = VkFrontFace.CounterClockwise; cfg.rasterizationState.depthClampEnable = False; cfg.rasterizationState.rasterizerDiscardEnable = False; cfg.rasterizationState.depthBiasEnable = False; cfg.rasterizationState.lineWidth = 1.0f; cfg.blendAttachments.Add(new VkPipelineColorBlendAttachmentState(false)); if (width < 0) { cfg.dynamicStates.Add(VkDynamicState.Viewport); cfg.dynamicStates.Add(VkDynamicState.Scissor); } else { cfg.Viewports.Add(new VkViewport { height = height, width = width, minDepth = 0f, maxDepth = 1f }); cfg.Scissors.Add(new VkRect2D((uint)width, (uint)height)); } if (depthTestEnabled) { cfg.depthStencilState.depthTestEnable = True; cfg.depthStencilState.depthWriteEnable = True; cfg.depthStencilState.depthCompareOp = VkCompareOp.LessOrEqual; cfg.depthStencilState.depthBoundsTestEnable = False; cfg.depthStencilState.back.failOp = VkStencilOp.Keep; cfg.depthStencilState.back.passOp = VkStencilOp.Keep; cfg.depthStencilState.back.compareOp = VkCompareOp.Always; cfg.depthStencilState.stencilTestEnable = False; cfg.depthStencilState.front = cfg.depthStencilState.back; } return(cfg); }
public AttachmentInfo(uint width, uint height, uint layers, VkFormat format, VkImageUsageFlags usage, VkSampleCountFlags samples = VkSampleCountFlags.Count1) { this.Width = width; this.Height = height; this.Layers = layers; this.Usage = usage; attachmentDescription = new VkAttachmentDescription(format, samples); if (Device.IsDepthFormat(format)) { ClearValue = new VkClearDepthStencilValue(1, 0); } else { ClearValue = new VkClearColorValue(0, 0, 0, 1); } }
void initUIPipeline(VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1) { descriptorPool = new CVKL.DescriptorPool(dev, 1, new VkDescriptorPoolSize(VkDescriptorType.CombinedImageSampler)); descLayout = new CVKL.DescriptorSetLayout(dev, new VkDescriptorSetLayoutBinding(0, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler) ); CVKL.GraphicPipelineConfig cfg = CVKL.GraphicPipelineConfig.CreateDefault(VkPrimitiveTopology.TriangleList, samples, false); cfg.Layout = new CVKL.PipelineLayout(dev, descLayout); cfg.RenderPass = new CVKL.RenderPass(dev, swapChain.ColorFormat, samples); cfg.AddShader(VkShaderStageFlags.Vertex, "shaders/FullScreenQuad.vert.spv"); cfg.AddShader(VkShaderStageFlags.Fragment, "shaders/simpletexture.frag.spv"); cfg.blendAttachments[0] = new VkPipelineColorBlendAttachmentState(true); uiPipeline = new CVKL.GraphicPipeline(cfg); dsCrow = descriptorPool.Allocate(descLayout); }
public VkAttachmentDescription( VkFormat format, VkSampleCountFlags samples, VkAttachmentLoadOp loadOp, VkAttachmentStoreOp storeOp, VkAttachmentLoadOp stencilLoadOp, VkAttachmentStoreOp stencilStoreOp, VkImageLayout initialLayout, VkImageLayout finalLayout, VkAttachmentDescriptionFlags flags = VkAttachmentDescriptionFlags.None) { this.flags = flags; this.format = format; this.samples = samples; this.loadOp = loadOp; this.storeOp = storeOp; this.stencilLoadOp = stencilLoadOp; this.stencilStoreOp = stencilStoreOp; this.initialLayout = initialLayout; this.finalLayout = finalLayout; }
public VkAttachmentDescription( VkFormat format, VkSampleCountFlags samples = VkSampleCountFlags.Count1, VkAttachmentLoadOp loadOp = VkAttachmentLoadOp.Clear, VkAttachmentStoreOp storeOp = VkAttachmentStoreOp.Store, VkAttachmentLoadOp stencilLoadOp = VkAttachmentLoadOp.DontCare, VkAttachmentStoreOp stencilStoreOp = VkAttachmentStoreOp.DontCare, VkImageLayout initialLayout = VkImageLayout.Undefined, VkImageLayout finalLayout = VkImageLayout.PresentSrcKHR, VkAttachmentDescriptionFlags flags = VkAttachmentDescriptionFlags.None) { this.flags = flags; this.format = format; this.samples = samples; this.loadOp = loadOp; this.storeOp = storeOp; this.stencilLoadOp = stencilLoadOp; this.stencilStoreOp = stencilStoreOp; this.initialLayout = initialLayout; this.finalLayout = finalLayout; }
public Image(Device device, VkFormat format, VkImageUsageFlags usage, VkMemoryPropertyFlags _memoryPropertyFlags, uint width, uint height, VkImageType type = VkImageType.Image2D, VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1, VkImageTiling tiling = VkImageTiling.Optimal, uint mipsLevels = 1, uint layers = 1, uint depth = 1, VkImageCreateFlags createFlags = 0) : base(device, _memoryPropertyFlags) { info.imageType = type; info.format = format; info.extent.width = width; info.extent.height = height; info.extent.depth = depth; info.mipLevels = mipsLevels; info.arrayLayers = layers; info.samples = samples; info.tiling = tiling; info.usage = usage; info.initialLayout = (tiling == VkImageTiling.Optimal) ? VkImageLayout.Undefined : VkImageLayout.Preinitialized; info.sharingMode = VkSharingMode.Exclusive; info.flags = createFlags; Activate(); //DONT OVERRIDE Activate in derived classes!!!! }
public unsafe static Image Create(uint width, uint height, VkImageCreateFlags flags, uint layers, uint levels, VkFormat format, VkSampleCountFlags samples, VkImageUsageFlags usage) { var imageType = height == 1 ? width > 1 ? VkImageType.Image1D : VkImageType.Image2D : VkImageType.Image2D; var createInfo = new VkImageCreateInfo { sType = VkStructureType.ImageCreateInfo, flags = flags, imageType = imageType, format = format, extent = new VkExtent3D(width, height, 1), mipLevels = levels, arrayLayers = layers, samples = samples, tiling = VkImageTiling.Optimal, usage = usage, sharingMode = VkSharingMode.Exclusive, initialLayout = VkImageLayout.Undefined }; Image image = new Image(ref createInfo); return(image); }
public static VkSampleCountFlags ExtractMaxSampleCount(VkPhysicalDeviceProperties physical) { VkSampleCountFlags counts = physical.limits.framebufferColorSampleCounts & physical.limits.framebufferDepthSampleCounts; if ((counts & VkSampleCountFlags.Count64) != 0) { return(VkSampleCountFlags.Count64); } if ((counts & VkSampleCountFlags.Count32) != 0) { return(VkSampleCountFlags.Count32); } if ((counts & VkSampleCountFlags.Count16) != 0) { return(VkSampleCountFlags.Count16); } if ((counts & VkSampleCountFlags.Count8) != 0) { return(VkSampleCountFlags.Count8); } if ((counts & VkSampleCountFlags.Count4) != 0) { return(VkSampleCountFlags.Count4); } if ((counts & VkSampleCountFlags.Count2) != 0) { return(VkSampleCountFlags.Count2); } return(VkSampleCountFlags.Count1); }
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; } }
internal extern static void vkGetPhysicalDeviceSparseImageFormatProperties(IntPtr physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlags samples, VkImageUsageFlags usage, VkImageTiling tiling, ref UInt32 pPropertyCount, [In, Out] VkSparseImageFormatProperties[] pProperties);
public List <VkSparseImageFormatProperties> GetSparseImageFormatProperties(VkFormat format, VkImageType type, VkSampleCountFlags samples, VkImageUsageFlags usage, VkImageTiling tiling) { var result = new List <VkSparseImageFormatProperties>(); uint count = 0; Instance.Commands.getPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage, tiling, ref count, IntPtr.Zero); var resultNative = new MarshalledArray <VkSparseImageFormatProperties>((int)count); Instance.Commands.getPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage, tiling, ref count, resultNative.Address); using (resultNative) { for (int i = 0; i < count; i++) { var prop = resultNative[i]; result.Add(prop); } } return(result); }
public static ReadOnlySpan <VkSparseImageFormatProperties> vkGetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlags samples, VkImageUsageFlags usage, VkImageTiling tiling) { uint propertyCount = 0; vkGetPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage, tiling, &propertyCount, null); ReadOnlySpan <VkSparseImageFormatProperties> properties = new VkSparseImageFormatProperties[propertyCount]; fixed(VkSparseImageFormatProperties *propertiesPtr = properties) { vkGetPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage, tiling, &propertyCount, propertiesPtr); } return(properties); }
public RenderPass(Device device, VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1) : base(device) { Samples = samples; }
public AttachmentInfo(StringID id, SizeHint sizeHint, VkFormat format, VkImageUsageFlags usage, VkSampleCountFlags samples = VkSampleCountFlags.Count1) { this.id = id; this.SizeHint = sizeHint; this.Usage = usage; attachmentDescription = new VkAttachmentDescription(format, samples); if (Device.IsDepthFormat(format)) { ClearValue = new VkClearDepthStencilValue(1, 0); } else { ClearValue = new VkClearColorValue(0, 0, 0, 1); } }
public DebugDrawPipeline(Device dev, DescriptorSetLayout dsLayout, VkFormat colorFormat, VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1) : base(new RenderPass(dev, colorFormat), "Debug draw pipeline") { GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault(VkPrimitiveTopology.LineList, samples); cfg.rasterizationState.lineWidth = 1.0f; cfg.RenderPass = RenderPass; cfg.Layout = new PipelineLayout(dev, dsLayout); cfg.Layout.AddPushConstants( new VkPushConstantRange(VkShaderStageFlags.Vertex, (uint)Marshal.SizeOf <Matrix4x4> () * 2) ); cfg.AddVertexBinding(0, 6 * sizeof(float)); cfg.SetVertexAttributes(0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32b32Sfloat); cfg.blendAttachments[0] = new VkPipelineColorBlendAttachmentState(true); cfg.AddShader(VkShaderStageFlags.Vertex, "shaders/debug.vert.spv"); cfg.AddShader(VkShaderStageFlags.Fragment, "shaders/debug.frag.spv"); layout = cfg.Layout; init(cfg); Vertices = new HostBuffer(dev, VkBufferUsageFlags.VertexBuffer, vboLength); Vertices.Map(); }
void init(VkSampleCountFlags samples = VkSampleCountFlags.SampleCount4) { descriptorPool = new DescriptorPool(dev, 2, new VkDescriptorPoolSize(VkDescriptorType.UniformBuffer), new VkDescriptorPoolSize(VkDescriptorType.CombinedImageSampler) ); descLayoutMatrix = new DescriptorSetLayout(dev, new VkDescriptorSetLayoutBinding(0, VkShaderStageFlags.Vertex | VkShaderStageFlags.Fragment, VkDescriptorType.UniformBuffer), new VkDescriptorSetLayoutBinding(1, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler) ); descLayoutTextures = new DescriptorSetLayout(dev, new VkDescriptorSetLayoutBinding(0, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), new VkDescriptorSetLayoutBinding(1, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), new VkDescriptorSetLayoutBinding(2, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), new VkDescriptorSetLayoutBinding(3, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler), new VkDescriptorSetLayoutBinding(4, VkShaderStageFlags.Fragment, VkDescriptorType.CombinedImageSampler) ); dsMats = descriptorPool.Allocate(descLayoutMatrix); GraphicPipelineConfig cfg = GraphicPipelineConfig.CreateDefault(VkPrimitiveTopology.TriangleList, samples); cfg.Layout = new PipelineLayout(dev, descLayoutMatrix, descLayoutTextures); cfg.Layout.AddPushConstants( new VkPushConstantRange(VkShaderStageFlags.Vertex, (uint)Marshal.SizeOf <Matrix4x4> ()), new VkPushConstantRange(VkShaderStageFlags.Fragment, (uint)Marshal.SizeOf <Model.PbrMaterial> (), 64) ); cfg.RenderPass = new RenderPass(dev, swapChain.ColorFormat, dev.GetSuitableDepthFormat(), samples); cfg.AddVertexBinding <Model.Vertex> (0); cfg.SetVertexAttributes(0, VkFormat.R32g32b32Sfloat, VkFormat.R32g32b32Sfloat, VkFormat.R32g32Sfloat); cfg.AddShader(VkShaderStageFlags.Vertex, "shaders/pbrtest.vert.spv"); cfg.AddShader(VkShaderStageFlags.Fragment, "shaders/pbrtest.frag.spv"); pipeline = new GraphicPipeline(cfg); cfg.ResetShadersAndVerticesInfos(); cfg.AddShader(VkShaderStageFlags.Vertex, "shaders/FullScreenQuad.vert.spv"); cfg.AddShader(VkShaderStageFlags.Fragment, "shaders/simpletexture.frag.spv"); cfg.blendAttachments[0] = new VkPipelineColorBlendAttachmentState(true); uiPipeline = new GraphicPipeline(cfg); uboMats = new HostBuffer(dev, VkBufferUsageFlags.UniformBuffer, (ulong)Marshal.SizeOf <Matrices>()); uboMats.Map(); //permanent map DescriptorSetWrites uboUpdate = new DescriptorSetWrites(dsMats, descLayoutMatrix.Bindings[0]); uboUpdate.Write(dev, uboMats.Descriptor); cfg.Layout.SetName("Main Pipeline layout"); uboMats.SetName("uboMats"); descriptorPool.SetName("main pool"); descLayoutTextures.SetName("descLayoutTextures"); statPool = new PipelineStatisticsQueryPool(dev, VkQueryPipelineStatisticFlags.InputAssemblyVertices | VkQueryPipelineStatisticFlags.InputAssemblyPrimitives | VkQueryPipelineStatisticFlags.ClippingInvocations | VkQueryPipelineStatisticFlags.ClippingPrimitives | VkQueryPipelineStatisticFlags.FragmentShaderInvocations); timestampQPool = new TimestampQueryPool(dev); }
public static Image Load(Queue staggingQ, CommandPool staggingCmdPool, string ktxPath, VkImageUsageFlags usage = VkImageUsageFlags.Sampled, VkMemoryPropertyFlags memoryProperty = VkMemoryPropertyFlags.DeviceLocal, bool generateMipmaps = true, VkImageTiling tiling = VkImageTiling.Optimal) { Image img = null; using (Stream ktxStream = File.Open(ktxPath, FileMode.Open, FileAccess.Read)) { using (BinaryReader br = new BinaryReader(ktxStream)) { if (!br.ReadBytes(12).AreEquals(ktxSignature)) { throw new KtxException("Not a ktx file: " + ktxPath); } UInt32 endianness = br.ReadUInt32(); UInt32 glType = br.ReadUInt32(); UInt32 glTypeSize = br.ReadUInt32(); UInt32 glFormat = br.ReadUInt32(); UInt32 glInternalFormat = br.ReadUInt32(); UInt32 glBaseInternalFormat = br.ReadUInt32(); UInt32 pixelWidth = br.ReadUInt32(); UInt32 pixelHeight = br.ReadUInt32(); UInt32 pixelDepth = Math.Min(1, br.ReadUInt32()); UInt32 numberOfArrayElements = br.ReadUInt32(); //only for array text, else 0 UInt32 numberOfFaces = br.ReadUInt32(); //only for cube map, else UInt32 numberOfMipmapLevels = Math.Min(1, br.ReadUInt32()); UInt32 bytesOfKeyValueData = br.ReadUInt32(); VkFormat vkFormat = GLHelper.vkGetFormatFromOpenGLInternalFormat(glInternalFormat); if (vkFormat == VkFormat.Undefined) { vkFormat = GLHelper.vkGetFormatFromOpenGLFormat(glFormat, glType); if (vkFormat == VkFormat.Undefined) { throw new KtxException("Undefined format: " + ktxPath); } } VkFormatFeatureFlags phyFormatSupport = (tiling == VkImageTiling.Linear) ? staggingQ.Dev.phy.GetFormatProperties(vkFormat).linearTilingFeatures : staggingQ.Dev.phy.GetFormatProperties(vkFormat).optimalTilingFeatures; uint requestedMipsLevels = numberOfMipmapLevels; if (numberOfMipmapLevels == 1) { requestedMipsLevels = (generateMipmaps && phyFormatSupport.HasFlag(VkFormatFeatureFlags.BlitSrc | VkFormatFeatureFlags.BlitDst)) ? (uint)Math.Floor(Math.Log(Math.Max(pixelWidth, pixelHeight))) + 1 : 1; } if (tiling == VkImageTiling.Optimal) { usage |= VkImageUsageFlags.TransferDst; } if (generateMipmaps) { usage |= (VkImageUsageFlags.TransferSrc | VkImageUsageFlags.TransferDst); } VkImageCreateFlags createFlags = 0; VkImageType imgType = (pixelWidth == 0) ? throw new KtxException("pixelWidth must be > 0") : (pixelHeight == 0) ? imgType = VkImageType.Image1D : (pixelDepth == 0) ? imgType = VkImageType.Image2D : imgType = VkImageType.Image3D; VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1; if (numberOfFaces > 1) { if (imgType != VkImageType.Image2D) { throw new KtxException("cubemap faces must be 2D textures"); } createFlags = VkImageCreateFlags.CubeCompatible; samples = VkSampleCountFlags.SampleCount1; numberOfArrayElements = numberOfFaces; } else { numberOfFaces = 1; if (numberOfArrayElements == 0) { numberOfArrayElements = 1; } } if (imgType != VkImageType.Image3D) { pixelDepth = 1; } img = new Image(staggingQ.Dev, vkFormat, usage, memoryProperty, pixelWidth, pixelHeight, imgType, samples, tiling, requestedMipsLevels, numberOfArrayElements, pixelDepth, createFlags); byte[] keyValueDatas = br.ReadBytes((int)bytesOfKeyValueData); if (memoryProperty.HasFlag(VkMemoryPropertyFlags.DeviceLocal)) { ulong staggingSize = img.AllocatedDeviceMemorySize; using (HostBuffer stagging = new HostBuffer(staggingQ.Dev, VkBufferUsageFlags.TransferSrc, staggingSize)) { stagging.Map(); CommandBuffer cmd = staggingCmdPool.AllocateCommandBuffer(); cmd.Start(VkCommandBufferUsageFlags.OneTimeSubmit); img.SetLayout(cmd, VkImageAspectFlags.Color, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal, VkPipelineStageFlags.AllCommands, VkPipelineStageFlags.Transfer); List <VkBufferImageCopy> buffCopies = new List <VkBufferImageCopy> (); VkBufferImageCopy bufferCopyRegion = new VkBufferImageCopy { imageExtent = img.CreateInfo.extent, imageSubresource = new VkImageSubresourceLayers(VkImageAspectFlags.Color, img.CreateInfo.arrayLayers, 0) }; ulong bufferOffset = 0; uint imgWidth = img.CreateInfo.extent.height; uint imgHeight = img.CreateInfo.extent.width; for (int mips = 0; mips < numberOfMipmapLevels; mips++) { UInt32 imgSize = br.ReadUInt32(); bufferCopyRegion.bufferImageHeight = imgWidth; bufferCopyRegion.bufferRowLength = imgHeight; bufferCopyRegion.bufferOffset = bufferOffset; if (createFlags.HasFlag(VkImageCreateFlags.CubeCompatible)) { IntPtr ptrFace = img.MappedData; bufferCopyRegion.imageSubresource.layerCount = 1; for (uint face = 0; face < numberOfFaces; face++) { bufferCopyRegion.imageSubresource.baseArrayLayer = face; Marshal.Copy(br.ReadBytes((int)imgSize), 0, stagging.MappedData + (int)bufferOffset, (int)imgSize); buffCopies.Add(bufferCopyRegion); uint faceOffset = imgSize + (imgSize % 4); ptrFace += (int)faceOffset; //cube padding bufferOffset += faceOffset; bufferCopyRegion.bufferOffset = bufferOffset; } } else { Marshal.Copy(br.ReadBytes((int)imgSize), 0, stagging.MappedData, (int)imgSize); buffCopies.Add(bufferCopyRegion); } bufferOffset += imgSize; imgWidth /= 2; imgHeight /= 2; } stagging.Unmap(); Vk.vkCmdCopyBufferToImage(cmd.Handle, stagging.handle, img.handle, VkImageLayout.TransferDstOptimal, (uint)buffCopies.Count, buffCopies.Pin()); buffCopies.Unpin(); if (requestedMipsLevels > numberOfMipmapLevels) { img.BuildMipmaps(cmd); } else { img.SetLayout(cmd, VkImageAspectFlags.Color, VkImageLayout.TransferDstOptimal, VkImageLayout.ShaderReadOnlyOptimal, VkPipelineStageFlags.Transfer, VkPipelineStageFlags.AllGraphics); } cmd.End(); staggingQ.Submit(cmd); staggingQ.WaitIdle(); cmd.Free(); } //for (int mips = 0; mips < numberOfMipmapLevels; mips++) { //UInt32 imgSize = br.ReadUInt32 (); /*VkImageBlit imageBlit = new VkImageBlit { * srcSubresource = new VkImageSubresourceLayers(VkImageAspectFlags.Color, numberOfArrayElements, (uint)mips - 1), * srcOffsets_1 = new VkOffset3D((int)pixelWidth >> (mips - 1), (int)pixelHeight >> (mips - 1),1), * dstSubresource = new VkImageSubresourceLayers (VkImageAspectFlags.Color, numberOfArrayElements, (uint)mips), * dstOffsets_1 = new VkOffset3D ((int)pixelWidth >> mips, (int)pixelHeight >> mips, 1), * };*/ //for (int layer = 0; layer < numberOfArrayElements; layer++) { //for (int face = 0; face < numberOfFaces; face++) { //for (int slice = 0; slice < pixelDepth; slice++) { /*for (int y = 0; y < pixelHeight; y++) { * for (int x = 0; x < pixelWidth; x++) { * //Uncompressed texture data matches a GL_UNPACK_ALIGNMENT of 4. * } * }*/ //} //Byte cubePadding[0-3] //} //} //Byte mipPadding[0-3] //} } } } return(img); }
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.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); vkGetImageMemoryRequirements(gd.Device, _optimalImage, out VkMemoryRequirements memoryRequirements); VkMemoryBlock memoryToken = gd.MemoryManager.Allocate( gd.PhysicalDeviceMemProperties, memoryRequirements.memoryTypeBits, VkMemoryPropertyFlags.DeviceLocal, false, memoryRequirements.size, memoryRequirements.alignment); _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); vkGetBufferMemoryRequirements(_gd.Device, _stagingBuffer, out VkMemoryRequirements bufferMemReqs); _memoryBlock = _gd.MemoryManager.Allocate( _gd.PhysicalDeviceMemProperties, bufferMemReqs.memoryTypeBits, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent, true, bufferMemReqs.size, bufferMemReqs.alignment); result = vkBindBufferMemory(_gd.Device, _stagingBuffer, _memoryBlock.DeviceMemory, _memoryBlock.Offset); CheckResult(result); } ClearIfRenderTarget(); }
public static Image Load(Queue staggingQ, CommandPool staggingCmdPool, string ktxPath, VkImageUsageFlags usage = VkImageUsageFlags.Sampled, VkMemoryPropertyFlags memoryProperty = VkMemoryPropertyFlags.DeviceLocal, bool generateMipmaps = true, VkImageTiling tiling = VkImageTiling.Optimal) { Image img = null; using (Stream ktxStream = File.Open(ktxPath, FileMode.Open, FileAccess.Read)) { using (BinaryReader br = new BinaryReader(ktxStream)) { if (!br.ReadBytes(12).AreEquals(ktxSignature)) { throw new KtxException("Not a ktx file: " + ktxPath); } UInt32 endianness = br.ReadUInt32(); UInt32 glType = br.ReadUInt32(); UInt32 glTypeSize = br.ReadUInt32(); UInt32 glFormat = br.ReadUInt32(); UInt32 glInternalFormat = br.ReadUInt32(); UInt32 glBaseInternalFormat = br.ReadUInt32(); UInt32 pixelWidth = br.ReadUInt32(); UInt32 pixelHeight = br.ReadUInt32(); UInt32 pixelDepth = Math.Max(1, br.ReadUInt32()); UInt32 numberOfArrayElements = br.ReadUInt32(); //only for array text, else 0 UInt32 numberOfFaces = br.ReadUInt32(); //only for cube map, else 1 UInt32 numberOfMipmapLevels = Math.Max(1, br.ReadUInt32()); UInt32 bytesOfKeyValueData = br.ReadUInt32(); VkFormat vkFormat = GLHelper.vkGetFormatFromOpenGLInternalFormat(glInternalFormat); if (vkFormat == VkFormat.Undefined) { vkFormat = GLHelper.vkGetFormatFromOpenGLFormat(glFormat, glType); if (vkFormat == VkFormat.Undefined) { throw new KtxException("Undefined format: " + ktxPath); } } VkFormatProperties formatProperties = staggingQ.Dev.phy.GetFormatProperties(vkFormat); VkFormatFeatureFlags phyFormatSupport = (tiling == VkImageTiling.Linear) ? formatProperties.linearTilingFeatures : formatProperties.optimalTilingFeatures; uint requestedMipsLevels = numberOfMipmapLevels; if (numberOfMipmapLevels == 1) { requestedMipsLevels = (generateMipmaps && phyFormatSupport.HasFlag(VkFormatFeatureFlags.BlitSrc | VkFormatFeatureFlags.BlitDst)) ? (uint)Math.Floor(Math.Log(Math.Max(pixelWidth, pixelHeight))) + 1 : 1; } if (tiling == VkImageTiling.Optimal) { usage |= VkImageUsageFlags.TransferDst; } if (generateMipmaps) { usage |= (VkImageUsageFlags.TransferSrc | VkImageUsageFlags.TransferDst); } VkImageCreateFlags createFlags = 0; VkImageType imgType = (pixelWidth == 0) ? throw new KtxException("pixelWidth must be > 0") : (pixelHeight == 0) ? imgType = VkImageType.Image1D : (pixelDepth == 1) ? imgType = VkImageType.Image2D : imgType = VkImageType.Image3D; VkSampleCountFlags samples = VkSampleCountFlags.SampleCount1; if (numberOfFaces > 1) { if (imgType != VkImageType.Image2D) { throw new KtxException("cubemap faces must be 2D textures"); } createFlags = VkImageCreateFlags.CubeCompatible; samples = VkSampleCountFlags.SampleCount1; numberOfArrayElements = numberOfFaces; } else { numberOfFaces = 1; if (numberOfArrayElements == 0) { numberOfArrayElements = 1; } } if (!Image.CheckFormatIsSupported(usage, phyFormatSupport)) { throw new Exception($"Unsupported image format: {vkFormat}, {tiling}, {usage}"); } img = new Image(staggingQ.Dev, vkFormat, usage, memoryProperty, pixelWidth, pixelHeight, imgType, samples, tiling, requestedMipsLevels, numberOfArrayElements, pixelDepth, createFlags); byte[] keyValueDatas = br.ReadBytes((int)bytesOfKeyValueData); uint blockW, blockH; bool isCompressed = vkFormat.TryGetCompressedFormatBlockSize(out blockW, out blockH); uint blockSize = blockW * blockH; if (memoryProperty.HasFlag(VkMemoryPropertyFlags.DeviceLocal)) { ulong staggingSize = img.AllocatedDeviceMemorySize; Console.WriteLine($"KtxStream size = {ktxStream.Length}, img Allocation = {img.AllocatedDeviceMemorySize}"); using (HostBuffer stagging = new HostBuffer(staggingQ.Dev, VkBufferUsageFlags.TransferSrc, staggingSize)) { stagging.Map(); PrimaryCommandBuffer cmd = staggingCmdPool.AllocateAndStart(VkCommandBufferUsageFlags.OneTimeSubmit); img.SetLayout(cmd, VkImageAspectFlags.Color, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal, VkPipelineStageFlags.AllCommands, VkPipelineStageFlags.Transfer); List <VkBufferImageCopy> buffCopies = new List <VkBufferImageCopy> (); VkBufferImageCopy bufferCopyRegion = new VkBufferImageCopy { imageExtent = img.CreateInfo.extent, imageSubresource = new VkImageSubresourceLayers(VkImageAspectFlags.Color, img.CreateInfo.arrayLayers, 0) }; ulong bufferOffset = 0; uint imgWidth = img.CreateInfo.extent.width; uint imgHeight = img.CreateInfo.extent.height; for (int mips = 0; mips < numberOfMipmapLevels; mips++) { UInt32 imgSize = br.ReadUInt32(); bufferCopyRegion.bufferRowLength = imgWidth; bufferCopyRegion.bufferImageHeight = imgHeight; if (isCompressed && (imgWidth % blockW > 0 || imgHeight % blockH > 0)) { bufferCopyRegion.bufferRowLength += blockW - imgWidth % blockW; bufferCopyRegion.bufferImageHeight += blockH - imgHeight % blockH; } bufferCopyRegion.bufferOffset = bufferOffset; bufferCopyRegion.imageSubresource.mipLevel = (uint)mips; bufferCopyRegion.imageExtent.width = imgWidth; bufferCopyRegion.imageExtent.height = imgHeight; if (createFlags.HasFlag(VkImageCreateFlags.CubeCompatible)) { //TODO:handle compressed formats for (uint face = 0; face < numberOfFaces; face++) { Marshal.Copy(br.ReadBytes((int)imgSize), 0, stagging.MappedData + (int)bufferOffset, (int)imgSize); uint faceOffset = imgSize + (imgSize % 4); //cube padding bufferOffset += faceOffset; } buffCopies.Add(bufferCopyRegion); bufferCopyRegion.bufferOffset = bufferOffset; } else if (isCompressed && (imgWidth % blockW > 0 || imgHeight % blockH > 0)) { for (int line = 0; line < imgHeight; line++) { Marshal.Copy(br.ReadBytes((int)imgWidth), 0, stagging.MappedData + (int)bufferOffset, (int)imgWidth); bufferOffset += bufferCopyRegion.bufferRowLength; } buffCopies.Add(bufferCopyRegion); } else { Marshal.Copy(br.ReadBytes((int)imgSize), 0, stagging.MappedData + (int)bufferOffset, (int)imgSize); buffCopies.Add(bufferCopyRegion); bufferOffset += imgSize; } if (isCompressed && bufferOffset % blockSize > 0) { bufferOffset += blockSize - bufferOffset % blockSize; } imgWidth /= 2; imgHeight /= 2; } stagging.Unmap(); Vk.vkCmdCopyBufferToImage(cmd.Handle, stagging.handle, img.handle, VkImageLayout.TransferDstOptimal, (uint)buffCopies.Count, buffCopies.Pin()); buffCopies.Unpin(); if (requestedMipsLevels > numberOfMipmapLevels) { img.BuildMipmaps(cmd); } else { img.SetLayout(cmd, VkImageAspectFlags.Color, VkImageLayout.TransferDstOptimal, VkImageLayout.ShaderReadOnlyOptimal, VkPipelineStageFlags.Transfer, VkPipelineStageFlags.FragmentShader); } cmd.End(); staggingQ.Submit(cmd); staggingQ.WaitIdle(); cmd.Free(); } } else { } } } return(img); }