public void InitializeVulkan() { // Create the VUlkan instance that we will use for this app _Instance = new VkInstance("Triangle - Sample", 1, "Ratchet", 1); // Now lets walk all physical device and find the first one that supports graphics queue foreach (VkPhysicalDevice physicalDevice in _Instance.vkEnumeratePhysicalDevices()) { foreach (VkQueueFamilyProperties queueFamilly in physicalDevice.QueueFamilies) { if ((queueFamilly.queueFlags & VkQueueFlags.VK_QUEUE_GRAPHICS) != 0) { // We have a physical device that supports graphics queue, we can now create a Device on it // with one queue and use it as our main device for this sample _Device = physicalDevice.CreateDevice(new VkDeviceQueueCreateInfo[] { new VkDeviceQueueCreateInfo() { queueCount = 1, queueFamily = queueFamilly, queuePriorities = new float[] { 1.0f } } }); // Ok now lets grab the graphics queue back. Technically there should only be one // But just to be clean we do an iteration and look for the queue that matches our // need foreach (VkQueue queue in _Device.Queues) { if (queue.Family.queueFlags == queueFamilly.queueFlags) { _Queue = queue; break; } } } } } }
/** * Finish command buffer recording and submit it to a queue * * @param commandBuffer Command buffer to flush * @param queue Queue to submit the command buffer to * @param free (Optional) Free the command buffer once it has been submitted (Defaults to true) * * @note The queue that the command buffer is submitted to must be from the same family index as the pool it was allocated from * @note Uses a fence to ensure command buffer has finished executing */ public void flushCommandBuffer(VkCommandBuffer commandBuffer, VkQueue queue, bool free = true) { if (commandBuffer.handle == 0) { return; } vkEndCommandBuffer(commandBuffer); VkSubmitInfo submitInfo = new VkSubmitInfo(); submitInfo.sType = SubmitInfo; submitInfo.commandBuffers = commandBuffer; // Create fence to ensure that the command buffer has finished executing VkFenceCreateInfo fenceInfo = new VkFenceCreateInfo(); fenceInfo.sType = FenceCreateInfo; fenceInfo.flags = 0; VkFence fence; vkCreateFence(_logicalDevice, &fenceInfo, null, &fence); // Submit to the queue vkQueueSubmit(queue, 1, &submitInfo, fence); // Wait for the fence to signal that command buffer has finished executing vkWaitForFences(_logicalDevice, 1, &fence, true, DEFAULT_FENCE_TIMEOUT); vkDestroyFence(_logicalDevice, fence, null); if (free) { vkFreeCommandBuffers(_logicalDevice, CommandPool, 1, &commandBuffer); } }
public void Submit(CommandBuffer buffer, VkSemaphore?wait = null, VkPipelineStageFlag waitStage = 0, VkSemaphore?signal = null, VkFence?submit = null) { buffer.AssertBuilt(); var buff = buffer.Handle; unsafe { var waitH = wait ?? VkSemaphore.Null; var signalH = signal ?? VkSemaphore.Null; var submitH = submit ?? VkFence.Null; var info = new VkSubmitInfo() { SType = VkStructureType.SubmitInfo, PNext = IntPtr.Zero, CommandBufferCount = 1, PCommandBuffers = &buff, SignalSemaphoreCount = signalH != VkSemaphore.Null ? 1u : 0u, PSignalSemaphores = &signalH, WaitSemaphoreCount = waitH != VkSemaphore.Null ? 1u : 0u, PWaitSemaphores = &waitH, PWaitDstStageMask = &waitStage, }; if (buffer is CommandBufferPooledExclusiveUse peu) { Debug.Assert(submitH == VkFence.Null, "Can't use a submit fence on a pooled handle"); peu.DoSubmit(Handle, info); } else { VkException.Check(VkQueue.vkQueueSubmit(Handle, 1, &info, submitH)); } } }
public void Render() { if (!isInitialized) { return; } if (this.submitInfos == null) { InitRenderParams(); } VkDevice device = this.device; VkSwapchainKHR swapchain = this.swapchain; VkSemaphore semaphore = this.vkSemaphore; VkFence fence = this.vkFence; VkQueue queue = this.vkQueue; //uint nextIndex = device.AcquireNextImageKHR(swapchain, ulong.MaxValue, semaphore); UInt32 nextIndex; vkAPI.vkAcquireNextImageKHR(device, swapchain, ulong.MaxValue, semaphore, new VkFence(), &nextIndex).Check(); //device.ResetFence(fence); vkAPI.vkResetFences(device, 1, &fence).Check(); //queue.Submit(ref this.submitInfos[nextIndex], fence); //VkSubmitInfo submitInfo = this.submitInfos[nextIndex]; //vkAPI.vkQueueSubmit(queue, 1, &submitInfo, fence).Check(); vkAPI.vkQueueSubmit(queue, 1, &this.submitInfos[nextIndex], fence).Check(); //device.WaitForFence(fence, true, 100000000); vkAPI.vkWaitForFences(device, 1, &fence, true, 100000000).Check(); //queue.PresentKHR(ref this.presentInfos[nextIndex]); //VkPresentInfoKHR presentInfo = this.presentInfos[nextIndex]; //vkAPI.vkQueuePresentKHR(queue, &presentInfo).Check(); vkAPI.vkQueuePresentKHR(queue, &this.presentInfos[nextIndex]).Check(); }
/// <summary> /// Submit an executable command buffer with optional wait and signal semaphores, and an optional fence to be signaled when the commands have been completed. /// </summary> /// <param name="queue">Queue.</param> /// <param name="wait">Wait.</param> /// <param name="signal">Signal.</param> /// <param name="fence">Fence.</param> public void Submit(VkQueue queue, VkSemaphore wait = default, VkSemaphore signal = default, Fence fence = null) { VkSubmitInfo submit_info = VkSubmitInfo.New(); IntPtr dstStageMask = Marshal.AllocHGlobal(sizeof(uint)); Marshal.WriteInt32(dstStageMask, (int)VkPipelineStageFlags.ColorAttachmentOutput); using (PinnedObjects pctx = new PinnedObjects()) { submit_info.pWaitDstStageMask = dstStageMask; if (signal != VkSemaphore.Null) { submit_info.signalSemaphoreCount = 1; submit_info.pSignalSemaphores = signal.Pin(pctx); } if (wait != VkSemaphore.Null) { submit_info.waitSemaphoreCount = 1; submit_info.pWaitSemaphores = wait.Pin(pctx); } submit_info.commandBufferCount = 1; submit_info.pCommandBuffers = handle.Pin(pctx); Utils.CheckResult(vkQueueSubmit(queue, 1, ref submit_info, fence)); } Marshal.FreeHGlobal(dstStageMask); }
/** * Finish command buffer recording and submit it to a queue * * @param commandBuffer Command buffer to flush * @param queue Queue to submit the command buffer to * @param free (Optional) Free the command buffer once it has been submitted (Defaults to true) * * @note The queue that the command buffer is submitted to must be from the same family index as the pool it was allocated from * @note Uses a fence to ensure command buffer has finished executing */ public void flushCommandBuffer(VkCommandBuffer commandBuffer, VkQueue queue, bool free = true) { if (commandBuffer.Handle == NullHandle) { return; } Util.CheckResult(vkEndCommandBuffer(commandBuffer)); VkSubmitInfo submitInfo = VkSubmitInfo.New(); submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &commandBuffer; // Create fence to ensure that the command buffer has finished executing VkFenceCreateInfo fenceInfo = VkFenceCreateInfo.New(); fenceInfo.flags = VkFenceCreateFlags.None; VkFence fence; Util.CheckResult(vkCreateFence(_logicalDevice, &fenceInfo, null, &fence)); // Submit to the queue Util.CheckResult(vkQueueSubmit(queue, 1, &submitInfo, fence)); // Wait for the fence to signal that command buffer has finished executing Util.CheckResult(vkWaitForFences(_logicalDevice, 1, &fence, True, DEFAULT_FENCE_TIMEOUT)); vkDestroyFence(_logicalDevice, fence, null); if (free) { vkFreeCommandBuffers(_logicalDevice, CommandPool, 1, &commandBuffer); } }
public static VkResult vkQueueBindSparse(VkQueue queue, ReadOnlySpan <VkBindSparseInfo> bindInfo, VkFence fence) { fixed(VkBindSparseInfo *bindInfoPtr = bindInfo) { return(vkQueueBindSparse(queue, bindInfo.Length, bindInfoPtr, fence)); } }
public static VkResult vkQueueSubmit(VkQueue queue, ReadOnlySpan <VkSubmitInfo> submits, VkFence fence) { fixed(VkSubmitInfo *submitsPtr = submits) { return(vkQueueSubmit(queue, submits.Length, submitsPtr, fence)); } }
internal Queue(Device device, VkQueue queue, uint familyIndex) { this.device = device; this.queue = queue; FamilyIndex = familyIndex; Family = device.PhysicalDevice.QueueFamilies[(int)familyIndex]; }
private void CreateLogicalDevice() { var indices = new QueueFamilyIndices(vkPhysicalDevice, vkSurface); float priority = 1f; var queueCreateInfos = stackalloc VkDeviceQueueCreateInfo[] { new VkDeviceQueueCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, queueFamilyIndex = (uint)indices.GraphicsFamily, queueCount = 1, pQueuePriorities = &priority, } }; int extensionsCount = 1; IntPtr *extensionsToEnableArray = stackalloc IntPtr[extensionsCount]; for (int i = 0; i < extensionsCount; i++) { string extension = "VK_KHR_swapchain"; extensionsToEnableArray[i] = Marshal.StringToHGlobalAnsi(extension); } VkPhysicalDeviceFeatures deviceFeatures = new VkPhysicalDeviceFeatures(); var createInfo = new VkDeviceCreateInfo() { sType = VkStructureType.VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, ppEnabledExtensionNames = (byte **)extensionsToEnableArray, enabledExtensionCount = (uint)extensionsCount, pQueueCreateInfos = queueCreateInfos, queueCreateInfoCount = 1, pEnabledFeatures = &deviceFeatures, }; VkDevice newDevice; var result = VulkanNative.vkCreateDevice(this.vkPhysicalDevice, &createInfo, null, &newDevice); this.vkDevice = newDevice; Helpers.CheckErrors(result); for (int i = 0; i < extensionsCount; i++) { Marshal.FreeHGlobal(extensionsToEnableArray[i]); } VkQueue newGraphicsQueue; VulkanNative.vkGetDeviceQueue(vkDevice, (uint)indices.GraphicsFamily, 0, &newGraphicsQueue); this.vkGraphicsQueue = newGraphicsQueue; VkQueue newPresentQueue; VulkanNative.vkGetDeviceQueue(vkDevice, (uint)indices.PresentFamily, 0, &newPresentQueue); this.vkPresentQueue = newPresentQueue; }
public void Submit(CommandBuffer[] buffers, VkSemaphore[] wait, VkPipelineStageFlag[] waitStages, VkSemaphore[] signal, VkFence submit) { unsafe { // ReSharper disable once PossibleNullReferenceException Debug.Assert((waitStages == null && wait == null) || waitStages.Length == wait.Length); var arrayBuffers = buffers.Where(x => !(x is CommandBufferPooledExclusiveUse)).Select(x => { x.AssertBuilt(); return(x.Handle); }).ToArray(); var pooledBuffers = buffers.OfType <CommandBufferPooledExclusiveUse>().ToArray(); Debug.Assert(pooledBuffers.Length == 0 || submit == VkFence.Null, "Can't use custom submit fence on pooled buffers"); fixed(VkSemaphore *waitPtr = wait) fixed(VkPipelineStageFlag * waitStagePtr = waitStages) fixed(VkSemaphore * signalPtr = signal) { if (arrayBuffers.Length > 0) fixed(VkCommandBuffer *buffer = arrayBuffers) { var info = new VkSubmitInfo() { SType = VkStructureType.SubmitInfo, PNext = IntPtr.Zero, CommandBufferCount = (uint)arrayBuffers.Length, PCommandBuffers = buffer, SignalSemaphoreCount = (uint)(signal?.Length ?? 0), PSignalSemaphores = signalPtr, WaitSemaphoreCount = (uint)(wait?.Length ?? 0), PWaitSemaphores = waitPtr, PWaitDstStageMask = waitStagePtr, }; VkException.Check(VkQueue.vkQueueSubmit(Handle, 1, &info, submit)); } foreach (var pooled in pooledBuffers) { var handle = pooled.Handle; var info = new VkSubmitInfo() { SType = VkStructureType.SubmitInfo, PNext = IntPtr.Zero, CommandBufferCount = 1, PCommandBuffers = &handle, SignalSemaphoreCount = (uint)(signal?.Length ?? 0), PSignalSemaphores = signalPtr, WaitSemaphoreCount = (uint)(wait?.Length ?? 0), PWaitSemaphores = waitPtr, PWaitDstStageMask = waitStagePtr, }; pooled.DoSubmit(Handle, info); } } } }
public static VkResult vkQueueSubmit(VkQueue queue, int submitCount, VkSubmitInfo[] pSubmits, VkFence fence) { VkPreconditions.CheckNull(queue, nameof(queue)); VkPreconditions.CheckNull(pSubmits, nameof(pSubmits)); VkPreconditions.CheckRange(submitCount, 1, int.MaxValue, nameof(submitCount)); VkPreconditions.CheckRange(pSubmits.Length < submitCount, nameof(pSubmits.Length)); return(GetQueue(queue).Submit(submitCount, pSubmits, fence)); }
/** * Queue an image for presentation * * @param queue Presentation queue for presenting the image * @param imageIndex Index of the swapchain image to queue for presentation * @param waitSemaphore (Optional) Semaphore that is waited on before the image is presented (only used if != VK_NULL_HANDLE) * * @return VkResult of the queue presentation */ public VkResult QueuePresent(VkQueue queue, uint imageIndex, VkSemaphore waitSemaphore = new VkSemaphore()) { var presentInfo = VkPresentInfoKHR.Alloc(); presentInfo->swapchainsImages.Set(Swapchain); presentInfo->swapchainsImages.Set(imageIndex); // Check if a wait semaphore has been specified to wait for before presenting the image if (waitSemaphore != 0ul) { presentInfo->waitSemaphores = waitSemaphore; } return(vkQueuePresentKHR(queue, presentInfo)); }
internal unsafe void SubmitCommand( VkQueue queue, List <Semaphore> signalSemaphores, List <Semaphore> waitSemaphores, VkPipelineStageFlags waitStageMask = VkPipelineStageFlags.TopOfPipe ) => SubmitCommands( new List <CommandBuffer> { this }, queue, signalSemaphores, waitSemaphores, waitStageMask );
/** * Queue an image for presentation * * @param queue Presentation queue for presenting the image * @param imageIndex Index of the swapchain image to queue for presentation * @param waitSemaphore (Optional) Semaphore that is waited on before the image is presented (only used if != VK_NULL_HANDLE) * * @return VkResult of the queue presentation */ public VkResult QueuePresent(VkQueue queue, uint imageIndex, VkSemaphore waitSemaphore = new VkSemaphore()) { VkPresentInfoKHR presentInfo = VkPresentInfoKHR.New(); presentInfo.pNext = null; presentInfo.swapchainCount = 1; var sc = Swapchain; presentInfo.pSwapchains = ≻ presentInfo.pImageIndices = &imageIndex; // Check if a wait semaphore has been specified to wait for before presenting the image if (waitSemaphore.Handle != 0) { presentInfo.pWaitSemaphores = &waitSemaphore; presentInfo.waitSemaphoreCount = 1; } return(vkQueuePresentKHR(queue, &presentInfo)); }
public void DeleteMessageInConversation(long conversationId, long messageId, bool clear) { try { VkApi.Messages.Delete(new[] { (ulong)messageId }, null, null, true); if (clear) { VkQueue = new VkQueue(); } Log.Message("VkModule", $"Message {messageId} deleted"); } catch (Exception e) { throw new VkBotException($"Can't delete message in conversation. Error : {e.Message}"); } }
public override void Init() { queue = Graphics.WorkQueue; scene = new Scene() { new Octree { }, new DebugRenderer { }, new Environment { SunlightDir = glm.normalize(new vec3(-1.0f, -1.0f, 0.0f)) }, new Node("Camera", new vec3(0, 2, -10), glm.radians(10, 0, 0)) { new Camera { NearClip = 0.5f, FarClip = 400, }, }, }; camera = scene.GetComponent <Camera>(true); PrepareSparseTexture(4096, 4096, 1, VkFormat.R8G8B8A8UNorm); { var node = scene.CreateChild("Plane"); var staticModel = node.AddComponent <StaticModel>(); var model = GeometryUtil.CreatePlaneModel(100, 100, 1, 1); staticModel.SetModel(model); var mat = new Material("shaders/VirtualTexture.shader"); mat.SetTexture("samplerColor", texture); staticModel.SetMaterial(mat); } MainView.Attach(camera, scene); }
private void CreateTexture(VkDevice device, VkPhysicalDevice physicalDevice, VkQueue graphicsQueue) { SimpleTgaReader tex = new SimpleTgaReader("resource/texture.tga"); var command = m_commandBuffers[1]; SampleHelpers.CreateTexture(device, physicalDevice, tex.Width, tex.Height, tex.ImageData, out m_image, out m_imageMemory, graphicsQueue, command); // イメージビューの作成. var imageViewCreateInfo = new VkImageViewCreateInfo() { image = m_image, viewType = VkImageViewType.VK_IMAGE_VIEW_TYPE_2D, format = VkFormat.VK_FORMAT_B8G8R8A8_UNORM, components = new VkComponentMapping(), subresourceRange = new VkImageSubresourceRange() { aspectMask = VkImageAspectFlags.VK_IMAGE_ASPECT_COLOR_BIT, baseArrayLayer = 0, baseMipLevel = 0, levelCount = 1, layerCount = 1, } }; VulkanAPI.vkCreateImageView(device, ref imageViewCreateInfo, out m_imageView); // サンプラーの作成. var samplerCreateInfo = new VkSamplerCreateInfo() { magFilter = VkFilter.VK_FILTER_LINEAR, minFilter = VkFilter.VK_FILTER_LINEAR, mipmapMode = VkSamplerMipmapMode.VK_SAMPLER_MIPMAP_MODE_NEAREST, addressModeU = VkSamplerAddressMode.VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, addressModeV = VkSamplerAddressMode.VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, }; VulkanAPI.vkCreateSampler(device, ref samplerCreateInfo, out m_imageSampler); }
protected void flushCommandBuffer(VkCommandBuffer commandBuffer, VkQueue queue, bool free) { if (commandBuffer.handle == 0) { return; } vkEndCommandBuffer(commandBuffer); VkSubmitInfo submitInfo = new VkSubmitInfo(); submitInfo.sType = SubmitInfo; submitInfo.commandBuffers = commandBuffer; vkQueueSubmit(queue, 1, &submitInfo, new VkFence()); vkQueueWaitIdle(queue); if (free) { vkFreeCommandBuffers(device, cmdPool, 1, &commandBuffer); } }
protected void flushCommandBuffer(VkCommandBuffer commandBuffer, VkQueue queue, bool free) { if (commandBuffer == NullHandle) { return; } Util.CheckResult(vkEndCommandBuffer(commandBuffer)); VkSubmitInfo submitInfo = VkSubmitInfo.New(); submitInfo.commandBufferCount = 1; submitInfo.pCommandBuffers = &commandBuffer; Util.CheckResult(vkQueueSubmit(queue, 1, &submitInfo, VkFence.Null)); Util.CheckResult(vkQueueWaitIdle(queue)); if (free) { vkFreeCommandBuffers(device, cmdPool, 1, &commandBuffer); } }
public static VkResult vkQueuePresentKHR(VkQueue queue, VkSemaphore waitSemaphore, VkSwapchainKHR swapchain, uint imageIndex) { var presentInfo = new VkPresentInfoKHR { sType = VkStructureType.PresentInfoKHR, pNext = null }; if (waitSemaphore != VkSemaphore.Null) { presentInfo.waitSemaphoreCount = 1u; presentInfo.pWaitSemaphores = &waitSemaphore; } if (swapchain != VkSwapchainKHR.Null) { presentInfo.swapchainCount = 1u; presentInfo.pSwapchains = &swapchain; presentInfo.pImageIndices = &imageIndex; } return(vkQueuePresentKHR(queue, &presentInfo)); }
void CreateDevice() { var features = physicalDevice.Features; var uniqueIndices = new HashSet <int> { graphicsIndex, presentIndex }; var priorities = new List <float> { 1f }; var queueInfos = new List <VkDeviceQueueCreateInfo>(uniqueIndices.Count); int i = 0; foreach (var ind in uniqueIndices) { var queueInfo = new VkDeviceQueueCreateInfo { queueFamilyIndex = ind, queueCount = 1, priorities = priorities }; queueInfos.Add(queueInfo); i++; } var info = new VkDeviceCreateInfo { extensions = deviceExtensions, queueCreateInfos = queueInfos, features = features }; device = new VkDevice(physicalDevice, info); graphicsQueue = device.GetQueue(graphicsIndex, 0); presentQueue = device.GetQueue(presentIndex, 0); }
public static extern VkResult QueueBindSparse( VkQueue queue, uint bindInfoCount, ref VkBindSparseInfo pBindInfo, VkFence fence );
public void Init(IntPtr hwnd, IntPtr processHandle) { if (this.isInitialized) { return; } this.instance = InitInstance(); InitDebugCallback(this.instance); this.surface = InitSurface(this.instance, hwnd, processHandle); this.vkPhysicalDevice = InitPhysicalDevice(this.instance); VkSurfaceFormatKHR surfaceFormat = SelectFormat(this.vkPhysicalDevice, this.surface); this.device = CreateDevice(this.vkPhysicalDevice, this.surface); this.vkQueue = this.device.GetQueue(0, 0); VkSurfaceCapabilitiesKHR surfaceCapabilities; //this.vkPhysicalDevice.GetSurfaceCapabilitiesKhr(this.vkSurface, out surfaceCapabilities); vkAPI.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(this.vkPhysicalDevice, this.surface, &surfaceCapabilities).Check(); this.swapchain = CreateSwapchain(this.device, this.surface, surfaceFormat, surfaceCapabilities); this.vkImages = this.device.GetSwapchainImages(this.swapchain); this.renderPass = CreateRenderPass(this.device, surfaceFormat); this.framebuffers = CreateFramebuffers(this.device, this.vkImages, surfaceFormat, this.renderPass, surfaceCapabilities); this.vkFence = this.device.CreateFence(); this.vkSemaphore = this.device.CreateSemaphore(); // buffers for vertex data. VkBuffer vertexBuffer = CreateBuffer(this.vkPhysicalDevice, this.device, Vertices, VkBufferUsageFlagBits.VertexBuffer, typeof(float)); VkBuffer indexBuffer = CreateBuffer(this.vkPhysicalDevice, this.device, Indexes, VkBufferUsageFlagBits.IndexBuffer, typeof(short)); var uniformBufferData = new AreaUniformBuffer(1, 1); this.originalWidth = 1; this.width = this.originalWidth; this.originalHeight = 1; this.height = this.originalHeight; this.uniformBuffer = CreateBuffer(this.vkPhysicalDevice, this.device, uniformBufferData, VkBufferUsageFlagBits.UniformBuffer, typeof(AreaUniformBuffer)); this.descriptorSetLayout = CreateDescriptorSetLayout(this.device); this.vkPipelineLayout = CreatePipelineLayout(this.device, this.descriptorSetLayout); VkPipeline pipeline = CreatePipeline(this.device, surfaceCapabilities, this.renderPass, this.vkPipelineLayout); this.descriptorSet = CreateDescriptorSet(this.device, this.descriptorSetLayout); UpdateDescriptorSets(this.device, this.uniformBuffer, this.descriptorSet); this.commandBuffers = CreateCommandBuffers( this.device, this.renderPass, surfaceCapabilities, this.vkImages, this.framebuffers, pipeline, vertexBuffer, indexBuffer, (uint)Indexes.Length, this.vkPipelineLayout, this.descriptorSet); this.isInitialized = true; }
/** * Load a 2D texture including all mip levels * * @param filename File to load (supports .ktx and .dds) * @param format Vulkan format of the image data stored in the file * @param device Vulkan device to create the texture on * @param copyQueue Queue used for the texture staging copy commands (must support transfer) * @param (Optional) imageUsageFlags Usage flags for the texture's image (defaults to VK_IMAGE_USAGE_SAMPLED_BIT) * @param (Optional) imageLayout Usage layout for the texture (defaults VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) * @param (Optional) forceLinear Force linear tiling (not advised, defaults to false) * */ public void loadFromFile( string filename, VkFormat format, vksVulkanDevice device, VkQueue copyQueue, VkImageUsageFlagBits imageUsageFlags = VkImageUsageFlagBits.Sampled, VkImageLayout imageLayout = VkImageLayout.ShaderReadOnlyOptimal, bool forceLinear = false) { KtxFile tex2D; using (var fs = File.OpenRead(filename)) { tex2D = KtxFile.Load(fs, false); } this.device = device; width = tex2D.Header.PixelWidth; height = tex2D.Header.PixelHeight; if (height == 0) { height = width; } mipLevels = tex2D.Header.NumberOfMipmapLevels; // Get device properites for the requested texture format VkFormatProperties formatProperties; vkGetPhysicalDeviceFormatProperties(device.PhysicalDevice, format, &formatProperties); // Only use linear tiling if requested (and supported by the device) // Support for linear tiling is mostly limited, so prefer to use // optimal tiling instead // On most implementations linear tiling will only support a very // limited amount of formats and features (mip maps, cubemaps, arrays, etc.) bool useStaging = !forceLinear; VkMemoryAllocateInfo memAllocInfo = new VkMemoryAllocateInfo(); memAllocInfo.sType = MemoryAllocateInfo; VkMemoryRequirements memReqs; // Use a separate command buffer for texture loading VkCommandBuffer copyCmd = device.createCommandBuffer(VkCommandBufferLevel.Primary, true); if (useStaging) { // Create a host-visible staging buffer that contains the raw image data VkBuffer stagingBuffer; VkDeviceMemory stagingMemory; VkBufferCreateInfo bufferCreateInfo = new VkBufferCreateInfo(); bufferCreateInfo.sType = BufferCreateInfo; bufferCreateInfo.size = tex2D.GetTotalSize(); // This buffer is used as a transfer source for the buffer copy bufferCreateInfo.usage = VkBufferUsageFlagBits.TransferSrc; bufferCreateInfo.sharingMode = VkSharingMode.Exclusive; vkCreateBuffer(device.LogicalDevice, &bufferCreateInfo, null, &stagingBuffer); // Get memory requirements for the staging buffer (alignment, memory type bits) vkGetBufferMemoryRequirements(device.LogicalDevice, stagingBuffer, &memReqs); memAllocInfo.allocationSize = memReqs.size; // Get memory type index for a host visible buffer memAllocInfo.memoryTypeIndex = device.getMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlagBits.HostVisible | VkMemoryPropertyFlagBits.HostCoherent); vkAllocateMemory(device.LogicalDevice, &memAllocInfo, null, &stagingMemory); vkBindBufferMemory(device.LogicalDevice, stagingBuffer, stagingMemory, 0); // Copy texture data into staging buffer IntPtr data; vkMapMemory(device.LogicalDevice, stagingMemory, 0, memReqs.size, 0, &data); byte[] pixelData = tex2D.GetAllTextureData(); fixed(byte *pixelDataPtr = &pixelData[0]) { Unsafe.CopyBlock(data, pixelDataPtr, (uint)pixelData.Length); } vkUnmapMemory(device.LogicalDevice, stagingMemory); // Setup buffer copy regions for each mip level var bufferCopyRegions = new List <VkBufferImageCopy>(); uint offset = 0; for (uint i = 0; i < mipLevels; i++) { VkBufferImageCopy bufferCopyRegion = new VkBufferImageCopy(); bufferCopyRegion.imageSubresource.aspectMask = VkImageAspectFlagBits.Color; bufferCopyRegion.imageSubresource.mipLevel = i; bufferCopyRegion.imageSubresource.baseArrayLayer = 0; bufferCopyRegion.imageSubresource.layerCount = 1; bufferCopyRegion.imageExtent.width = tex2D.Faces[0].Mipmaps[i].Width; bufferCopyRegion.imageExtent.height = tex2D.Faces[0].Mipmaps[i].Height; bufferCopyRegion.imageExtent.depth = 1; bufferCopyRegion.bufferOffset = offset; bufferCopyRegions.Add(bufferCopyRegion); offset += tex2D.Faces[0].Mipmaps[i].SizeInBytes; } // Create optimal tiled target image VkImageCreateInfo imageCreateInfo = new VkImageCreateInfo(); imageCreateInfo.sType = ImageCreateInfo; imageCreateInfo.imageType = VkImageType._2d; imageCreateInfo.format = format; imageCreateInfo.mipLevels = mipLevels; imageCreateInfo.arrayLayers = 1; imageCreateInfo.samples = VkSampleCountFlagBits._1; imageCreateInfo.tiling = VkImageTiling.Optimal; imageCreateInfo.sharingMode = VkSharingMode.Exclusive; imageCreateInfo.initialLayout = VkImageLayout.Undefined; imageCreateInfo.extent = new VkExtent3D { width = width, height = height, depth = 1 }; imageCreateInfo.usage = imageUsageFlags; // Ensure that the TRANSFER_DST bit is set for staging if ((imageCreateInfo.usage & VkImageUsageFlagBits.TransferDst) == 0) { imageCreateInfo.usage |= VkImageUsageFlagBits.TransferDst; } { VkImage vkImage; vkCreateImage(device.LogicalDevice, &imageCreateInfo, null, &vkImage); this.image = vkImage; } vkGetImageMemoryRequirements(device.LogicalDevice, image, &memReqs); memAllocInfo.allocationSize = memReqs.size; memAllocInfo.memoryTypeIndex = device.getMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlagBits.DeviceLocal); { VkDeviceMemory memory; vkAllocateMemory(device.LogicalDevice, &memAllocInfo, null, &memory); this.deviceMemory = memory; } vkBindImageMemory(device.LogicalDevice, image, deviceMemory, 0); VkImageSubresourceRange subresourceRange = new VkImageSubresourceRange(); subresourceRange.aspectMask = VkImageAspectFlagBits.Color; subresourceRange.baseMipLevel = 0; subresourceRange.levelCount = mipLevels; subresourceRange.layerCount = 1; // Image barrier for optimal image (target) // Optimal image will be used as destination for the copy Tools.setImageLayout( copyCmd, image, VkImageAspectFlagBits.Color, VkImageLayout.Undefined, VkImageLayout.TransferDstOptimal, subresourceRange); // Copy mip levels from staging buffer fixed(VkBufferImageCopy *pointer = bufferCopyRegions.ToArray()) { vkCmdCopyBufferToImage( copyCmd, stagingBuffer, image, VkImageLayout.TransferDstOptimal, (UInt32)bufferCopyRegions.Count, pointer); } // Change texture image layout to shader read after all mip levels have been copied this.imageLayout = imageLayout; Tools.setImageLayout( copyCmd, image, VkImageAspectFlagBits.Color, VkImageLayout.TransferDstOptimal, imageLayout, subresourceRange); device.flushCommandBuffer(copyCmd, copyQueue); // Clean up staging resources vkFreeMemory(device.LogicalDevice, stagingMemory, null); vkDestroyBuffer(device.LogicalDevice, stagingBuffer, null); } else { throw new NotImplementedException(); /* * // Prefer using optimal tiling, as linear tiling * // may support only a small set of features * // depending on implementation (e.g. no mip maps, only one layer, etc.) * * // Check if this support is supported for linear tiling * Debug.Assert((formatProperties.linearTilingFeatures & VkFormatFeatureFlags.SampledImage) != 0); * * VkImage mappableImage; * VkDeviceMemory mappableMemory; * * VkImageCreateInfo imageCreateInfo = Initializers.imageCreateInfo(); * imageCreateInfo.imageType = VkImageType._2d; * imageCreateInfo.format = format; * imageCreateInfo.extent = new VkExtent3D { width = width, height = height, depth = 1 }; * imageCreateInfo.mipLevels = 1; * imageCreateInfo.arrayLayers = 1; * imageCreateInfo.samples = VkSampleCountFlags._1; * imageCreateInfo.tiling = VkImageTiling.Linear; * imageCreateInfo.usage = imageUsageFlags; * imageCreateInfo.sharingMode = VkSharingMode.Exclusive; * imageCreateInfo.initialLayout = VkImageLayout.Undefined; * * // Load mip map level 0 to linear tiling image * Util.CheckResult(vkCreateImage(device.LogicalDevice, &imageCreateInfo, null, &mappableImage)); * * // Get memory requirements for this image * // like size and alignment * vkGetImageMemoryRequirements(device.LogicalDevice, mappableImage, &memReqs); * // Set memory allocation size to required memory size * memAllocInfo.allocationSize = memReqs.size; * * // Get memory type that can be mapped to host memory * memAllocInfo.memoryTypeIndex = device.GetMemoryType(memReqs.memoryTypeBits, VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent); * * // Allocate host memory * Util.CheckResult(vkAllocateMemory(device.LogicalDevice, &memAllocInfo, null, &mappableMemory)); * * // Bind allocated image for use * Util.CheckResult(vkBindImageMemory(device.LogicalDevice, mappableImage, mappableMemory, 0)); * * // Get sub resource layout * // Mip map count, array layer, etc. * VkImageSubresource subRes = new VkImageSubresource(); * subRes.aspectMask = VkImageAspectFlags.Color; * subRes.mipLevel = 0; * * VkSubresourceLayout subResLayout; * void* data; * * // Get sub resources layout * // Includes row pitch, size offsets, etc. * vkGetImageSubresourceLayout(device.LogicalDevice, mappableImage, &subRes, &subResLayout); * * // Map image memory * Util.CheckResult(vkMapMemory(device.LogicalDevice, mappableMemory, 0, memReqs.size, 0, &data)); * * // Copy image data into memory * memcpy(data, tex2D[subRes.mipLevel].data(), tex2D[subRes.mipLevel].size()); * * vkUnmapMemory(device.LogicalDevice, mappableMemory); * * // Linear tiled images don't need to be staged * // and can be directly used as textures * image = mappableImage; * deviceMemory = mappableMemory; * imageLayout = imageLayout; * * // Setup image memory barrier * vks::tools::setImageLayout(copyCmd, image, VkImageAspectFlags.Color, VkImageLayout.Undefined, imageLayout); * * device.flushCommandBuffer(copyCmd, copyQueue); */ } // Create a defaultsampler VkSamplerCreateInfo samplerCreateInfo = new VkSamplerCreateInfo(); samplerCreateInfo.sType = SamplerCreateInfo; samplerCreateInfo.magFilter = VkFilter.Linear; samplerCreateInfo.minFilter = VkFilter.Linear; samplerCreateInfo.mipmapMode = VkSamplerMipmapMode.Linear; samplerCreateInfo.addressModeU = VkSamplerAddressMode.Repeat; samplerCreateInfo.addressModeV = VkSamplerAddressMode.Repeat; samplerCreateInfo.addressModeW = VkSamplerAddressMode.Repeat; samplerCreateInfo.mipLodBias = 0.0f; samplerCreateInfo.compareOp = VkCompareOp.Never; samplerCreateInfo.minLod = 0.0f; // Max level-of-detail should match mip level count samplerCreateInfo.maxLod = (useStaging) ? (float)mipLevels : 0.0f; // Enable anisotropic filtering samplerCreateInfo.maxAnisotropy = 8; samplerCreateInfo.anisotropyEnable = true; samplerCreateInfo.borderColor = VkBorderColor.FloatOpaqueWhite; { VkSampler vkSampler; vkCreateSampler(device.LogicalDevice, &samplerCreateInfo, null, &vkSampler); this.sampler = vkSampler; } // Create image view // Textures are not directly accessed by the shaders and // are abstracted by image views containing additional // information and sub resource ranges VkImageViewCreateInfo viewCreateInfo = new VkImageViewCreateInfo(); viewCreateInfo.sType = ImageViewCreateInfo; viewCreateInfo.viewType = VkImageViewType._2d; viewCreateInfo.format = format; viewCreateInfo.components = new VkComponentMapping { r = VkComponentSwizzle.R, g = VkComponentSwizzle.G, b = VkComponentSwizzle.B, a = VkComponentSwizzle.A }; viewCreateInfo.subresourceRange = new VkImageSubresourceRange { aspectMask = VkImageAspectFlagBits.Color, baseMipLevel = 0, levelCount = 1, baseArrayLayer = 0, layerCount = 1 }; // Linear tiling usually won't support mip maps // Only set mip map count if optimal tiling is used viewCreateInfo.subresourceRange.levelCount = (useStaging) ? mipLevels : 1; viewCreateInfo.image = image; { VkImageView vkImageView; vkCreateImageView(device.LogicalDevice, &viewCreateInfo, null, &vkImageView); this.view = vkImageView; } // Update descriptor image info member that can be used for setting up descriptor sets updateDescriptor(); }
private static IVkQueue GetQueue(VkQueue queue) { return((IVkQueue)queue); }
public static VkResult vkQueueWaitIdle(VkQueue queue) { VkPreconditions.CheckNull(queue, nameof(queue)); return(GetQueue(queue).WaitIdle()); }
public static VkResult vkQueuePresentKHR(VkQueue queue, VkPresentInfoKHR pPresentInfo) { VkPreconditions.CheckNull(queue, nameof(queue)); return(GetQueue(queue).Present(pPresentInfo)); }
public static extern VkResult QueueWaitIdle( VkQueue queue );
public static void vkGetDeviceQueue(VkDevice device, int queueFamilyIndex, int queueIndex, out VkQueue pQueue) { VkPreconditions.CheckNull(device, nameof(device)); VkPreconditions.CheckRange(queueFamilyIndex, 0, int.MaxValue, nameof(queueFamilyIndex)); VkPreconditions.CheckRange(queueIndex, 0, int.MaxValue, nameof(queueIndex)); GetDevice(device).GetQueue(queueFamilyIndex, queueIndex, out pQueue); }