def draw(self): nextBuffer = self.swapChain.acquireNextImage( self.semaphores['presentComplete'], self.currentBuffer) self.currentBuffer = nextBuffer #print(nextBuffer) # Use a fence to wait until the command buffer has finished execution before using it again vk.vkWaitForFences(self.device, 1, [self.waitFences[self.currentBuffer]], vk.VK_TRUE, vk.UINT64_MAX) vk.vkResetFences(self.device, 1, [self.waitFences[self.currentBuffer]]) # Pipeline stage at which the queue submission will wait (via pWaitSemaphores) waitStageMask = vk.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT # The submit info structure specifices a command buffer queue submission batch submitInfo = vk.VkSubmitInfo( sType=vk.VK_STRUCTURE_TYPE_SUBMIT_INFO, pWaitDstStageMask=[waitStageMask], pWaitSemaphores=[self.semaphores['presentComplete']], waitSemaphoreCount=1, signalSemaphoreCount=1, pSignalSemaphores=[self.semaphores['renderComplete']], pCommandBuffers=[self.drawCmdBuffers[self.currentBuffer]], commandBufferCount=1) # Submit to the graphics queue passing a wait fence vk.vkQueueSubmit(self.queue, 1, submitInfo, self.waitFences[self.currentBuffer]) # Present the current buffer to the swap chain # Pass the semaphore signaled by the command buffer submission from the submit info as the wait semaphore for swap chain presentation # This ensures that the image is not presented to the windowing system until all commands have been submitted try: self.swapChain.queuePresent(self.queue, self.currentBuffer, self.semaphores['renderComplete']) except vk.VkErrorOutOfDateKhr: self.windowResize()
def swap(self, semaphores=None): """Display final image on screen. This function makes all the rendering work. To proceed, it copies the `final_image` into the current swapchain image previously acquired. You can pass custom semaphores (and you should) to synchronize the command. Args: semaphore (list[Semaphore]): semaphores to wait on **Note: `final_image` layout is handled by `VulkContext`. You must let it to COLOR_ATTACHMENT_OPTIMAL** """ # Acquire image try: index = self.pfn['vkAcquireNextImageKHR']( self.device, self.swapchain, vk.UINT64_MAX, self._semaphore_available.semaphore, None) except vk.VkErrorOutOfDateKhr: logger.warning("Swapchain out of date, reloading...") self.reload_swapchain() return wait_semaphores = [self._semaphore_available] if semaphores: wait_semaphores.extend([s for s in semaphores if s]) wait_masks = [vc.PipelineStage.COLOR_ATTACHMENT_OUTPUT] wait_masks *= len(wait_semaphores) copied_semaphores = [self._semaphore_copied.semaphore] # Transfer final image to swapchain image submit = vk.VkSubmitInfo( sType=vk.VK_STRUCTURE_TYPE_SUBMIT_INFO, waitSemaphoreCount=len(wait_semaphores), pWaitSemaphores=[s.semaphore for s in wait_semaphores], pWaitDstStageMask=wait_masks, commandBufferCount=1, pCommandBuffers=[self.commandbuffers[index].commandbuffer], signalSemaphoreCount=len(copied_semaphores), pSignalSemaphores=copied_semaphores) vk.vkQueueSubmit(self.graphic_queue, 1, [submit], None) # Present swapchain image on screen present = vk.VkPresentInfoKHR( sType=vk.VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, waitSemaphoreCount=len(copied_semaphores), pWaitSemaphores=copied_semaphores, swapchainCount=1, pSwapchains=[self.swapchain], pImageIndices=[index], pResults=None) self.pfn['vkQueuePresentKHR'](self.present_queue, present) vk.vkDeviceWaitIdle(self.device)
def submit(self, command_buffer: CommandBuffer, render_semaphore: VulkanSemaphore, image_semaphore: VulkanSemaphore): submit = vulkan.VkSubmitInfo( pWaitSemaphores=[image_semaphore.vk_semaphore], pWaitDstStageMask=[ vulkan.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT ], pCommandBuffers=[command_buffer.vk_command_buffer], pSignalSemaphores=[render_semaphore.vk_semaphore]) vulkan.vkQueueSubmit(self.vk_queue, 1, submit, None)
def draw(self): super().prepareFrame() # self.submitInfo.commandBufferCount = 1 # TODO try to avoid creating submitInfo at each frame # need to get CData pointer on drawCmdBuffers[*] # self.submitInfo.pCommandBuffers[0] = self.drawCmdBuffers[self.currentBuffer] # vk.vkQueueSubmit(self.queue, 1, self.submit_list, vk.VK_NULL_HANDLE) submitInfo = vk.VkSubmitInfo( sType=vk.VK_STRUCTURE_TYPE_SUBMIT_INFO, pWaitDstStageMask=[ vk.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT ], pWaitSemaphores=[self.semaphores['presentComplete']], waitSemaphoreCount=1, signalSemaphoreCount=1, pSignalSemaphores=[self.semaphores['renderComplete']], pCommandBuffers=[self.drawCmdBuffers[self.currentBuffer]], commandBufferCount=1) vk.vkQueueSubmit(self.queue, 1, submitInfo, vk.VK_NULL_HANDLE) super().submitFrame()
def flushCommandBuffer(self, commandBuffer): """ End the command buffer and submit it to the queue Uses a fence to ensure command buffer has finished executing before deleting it """ assert (commandBuffer != vk.VK_NULL_HANDLE) vk.vkEndCommandBuffer(commandBuffer) submitInfo = vk.VkSubmitInfo(sType=vk.VK_STRUCTURE_TYPE_SUBMIT_INFO, commandBufferCount=1, pCommandBuffers=[commandBuffer]) # Create fence to ensure that the command buffer has finished executing fenceCreateInfo = vk.VkFenceCreateInfo( sType=vk.VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, flags=0) fence = vk.vkCreateFence(self.device, fenceCreateInfo, None) # Submit to the queue vk.vkQueueSubmit(self.queue, 1, [submitInfo], fence) # Wait for the fence to signal that command buffer has finished executing vk.vkWaitForFences(self.device, 1, [fence], vk.VK_TRUE, vks.vulkanglobals.DEFAULT_FENCE_TIMEOUT) vk.vkDestroyFence(self.device, fence, None) vk.vkFreeCommandBuffers(self.device, self.cmdPool, 1, [commandBuffer])
def loadMeshes(self, copyCmd): # allocate numpy arrays vertexCount = 0 indexCount = 0 for aMesh in self.aScene.meshes: vertexCount += len(aMesh.vertices) indexCount += len(aMesh.faces) * 3 vertices = np.empty((vertexCount, ), dtype=self.vertexShape) indices = np.empty((indexCount, ), dtype=np.uint32) indexBase = 0 vertexCount = 0 indexCount = 0 for aMesh in self.aScene.meshes: print("Mesh \"" + aMesh.name + "\"") print(" Material: \"" + self.materials[aMesh.materialindex]["name"] + "\"") print(" Faces: " + str(len(aMesh.faces))) scenepart = { 'material': self.materials[aMesh.materialindex], 'indexBase': indexBase, 'indexCount': len(aMesh.faces) * 3 } self.meshes.append(scenepart) # Vertices hasUV = len(aMesh.texturecoords) > 0 hasColor = len(aMesh.colors) > 0 hasNormals = len(aMesh.normals) > 0 print(" hasUV", hasUV, "hasColor", hasColor, "hasNormals", hasNormals) for v in range(len(aMesh.vertices)): vertices[vertexCount]['pos'] = aMesh.vertices[v] vertices[vertexCount]['pos'] = -vertices[vertexCount]['pos'] vertices[vertexCount]['uv'] = aMesh.texturecoords[0][ v][:2] if hasUV else [0.0, 0.0] vertices[vertexCount]['normal'] = aMesh.normals[ v] if hasNormals else [0.0, 0.0, 0.0] vertices[vertexCount][ 'normal'] = -vertices[vertexCount]['normal'] vertices[vertexCount]['color'] = aMesh.colors[ v] if hasColor else [1.0, 1.0, 1.0] vertexCount += 1 # Indices for f in range(len(aMesh.faces)): for j in range(3): indices[indexCount] = aMesh.faces[f][j] indexCount += 1 indexBase += len(aMesh.faces) * 3 # Create buffers # For better performance we only create one index and vertex buffer to keep number of memory allocations down vertexDataSize = vertices.size * vertices.itemsize indexDataSize = indices.size * indices.itemsize # Vertex buffer # Staging buffer vertexStaging = self.vulkanDevice.createvksBuffer( vk.VK_BUFFER_USAGE_TRANSFER_SRC_BIT, vk.VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | vk.VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, vertexDataSize, vertices) # Target self.vertexBuffer = self.vulkanDevice.createvksBuffer( vk.VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | vk.VK_BUFFER_USAGE_TRANSFER_DST_BIT, vk.VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, vertexDataSize) # Index buffer # Staging buffer indexStaging = self.vulkanDevice.createvksBuffer( vk.VK_BUFFER_USAGE_TRANSFER_SRC_BIT, vk.VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | vk.VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, indexDataSize, indices) # Target self.indexBuffer = self.vulkanDevice.createvksBuffer( vk.VK_BUFFER_USAGE_INDEX_BUFFER_BIT | vk.VK_BUFFER_USAGE_TRANSFER_DST_BIT, vk.VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, indexDataSize) # Copy cmdBufInfo = vk.VkCommandBufferBeginInfo( sType=vk.VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, ) vk.vkBeginCommandBuffer(copyCmd, cmdBufInfo) copyRegion = vk.VkBufferCopy(size=vertexDataSize) vk.vkCmdCopyBuffer(copyCmd, vertexStaging.buffer, self.vertexBuffer.buffer, 1, copyRegion) copyRegion = vk.VkBufferCopy(size=indexDataSize) vk.vkCmdCopyBuffer(copyCmd, indexStaging.buffer, self.indexBuffer.buffer, 1, copyRegion) vk.vkEndCommandBuffer(copyCmd) submitInfo = vk.VkSubmitInfo(sType=vk.VK_STRUCTURE_TYPE_SUBMIT_INFO, pCommandBuffers=[copyCmd], commandBufferCount=1) vk.vkQueueSubmit(self.queue, 1, submitInfo, vk.VK_NULL_HANDLE) vk.vkQueueWaitIdle(self.queue) vertexStaging.destroy() indexStaging.destroy()