def begin(self): begin = vulkan.VkCommandBufferBeginInfo( flags=vulkan.VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, pInheritanceInfo=None) vulkan.vkBeginCommandBuffer(self.vk_command_buffer, begin)
def buildCommandBuffers(self): cmdBufInfo = vk.VkCommandBufferBeginInfo( sType=vk.VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, pNext=None) clearValues = [] clearValue = vk.VkClearValue(color=self.defaultClearColor) clearValues.append(clearValue) clearValue = vk.VkClearValue(depthStencil=[1.0, 0]) clearValues.append(clearValue) offset = vk.VkOffset2D(x=0, y=0) extent = vk.VkExtent2D(width=self.width, height=self.height) renderArea = vk.VkRect2D(offset=offset, extent=extent) renderPassBeginInfo = vk.VkRenderPassBeginInfo( sType=vk.VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, pNext=None, renderPass=self.renderPass, renderArea=renderArea, clearValueCount=2, pClearValues=clearValues, ) for i in range(len(self.drawCmdBuffers)): renderPassBeginInfo.framebuffer = self.frameBuffers[i] vk.vkBeginCommandBuffer(self.drawCmdBuffers[i], cmdBufInfo) vk.vkCmdBeginRenderPass(self.drawCmdBuffers[i], renderPassBeginInfo, vk.VK_SUBPASS_CONTENTS_INLINE) viewport = vk.VkViewport(height=float(self.height), width=float(self.width), minDepth=0.0, maxDepth=1.0) vk.vkCmdSetViewport(self.drawCmdBuffers[i], 0, 1, [viewport]) # Update dynamic scissor state offsetscissor = vk.VkOffset2D(x=0, y=0) extentscissor = vk.VkExtent2D(width=self.width, height=self.height) scissor = vk.VkRect2D(offset=offsetscissor, extent=extentscissor) vk.vkCmdSetScissor(self.drawCmdBuffers[i], 0, 1, [scissor]) vk.vkCmdBindDescriptorSets(self.drawCmdBuffers[i], vk.VK_PIPELINE_BIND_POINT_GRAPHICS, self.pipelineLayout, 0, 1, [self.descriptorSet], 0, None) vk.vkCmdBindPipeline(self.drawCmdBuffers[i], vk.VK_PIPELINE_BIND_POINT_GRAPHICS, self.pipelines['solid']) offsets = [0] vk.vkCmdBindVertexBuffers(self.drawCmdBuffers[i], VERTEX_BUFFER_BIND_ID, 1, [self.vertexBuffer.buffer], offsets) vk.vkCmdBindIndexBuffer(self.drawCmdBuffers[i], self.indexBuffer.buffer, 0, vk.VK_INDEX_TYPE_UINT32) # Draw indexed triangle vk.vkCmdDrawIndexed(self.drawCmdBuffers[i], self.indexCount, 1, 0, 0, 0) self.drawUI(self.drawCmdBuffers[i]) vk.vkCmdEndRenderPass(self.drawCmdBuffers[i]) vk.vkEndCommandBuffer(self.drawCmdBuffers[i])
def getCommandBuffer(self, begin): """ Get a new command buffer from the command pool If begin is true, the command buffer is also started so we can start adding commands """ cmdBufAllocateInfo = vk.VkCommandBufferAllocateInfo( sType=vk.VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, commandPool=self.cmdPool, level=vk.VK_COMMAND_BUFFER_LEVEL_PRIMARY, commandBufferCount=1) cmdBuffer = vk.vkAllocateCommandBuffers(self.device, cmdBufAllocateInfo)[0] if begin: cmdBufInfo = vk.VkCommandBufferBeginInfo( sType=vk.VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO) vk.vkBeginCommandBuffer(cmdBuffer, cmdBufInfo) return cmdBuffer
def buildCommandBuffers(self): cmdBufInfo = vk.VkCommandBufferBeginInfo( sType=vk.VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO) clearValues = [] clearValue = vk.VkClearValue(color=self.defaultClearColor) clearValues.append(clearValue) clearValue = vk.VkClearValue(depthStencil=[1.0, 0]) clearValues.append(clearValue) offset = vk.VkOffset2D(x=0, y=0) extent = vk.VkExtent2D(width=self.width, height=self.height) renderArea = vk.VkRect2D(offset=offset, extent=extent) renderPassBeginInfo = vk.VkRenderPassBeginInfo( sType=vk.VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, pNext=None, renderPass=self.renderPass, renderArea=renderArea, clearValueCount=2, pClearValues=clearValues, ) for i in range(len(self.drawCmdBuffers)): renderPassBeginInfo.framebuffer = self.frameBuffers[i] vk.vkBeginCommandBuffer(self.drawCmdBuffers[i], cmdBufInfo) vk.vkCmdBeginRenderPass(self.drawCmdBuffers[i], renderPassBeginInfo, vk.VK_SUBPASS_CONTENTS_INLINE) viewport = vk.VkViewport(height=float(self.height), width=float(self.width), minDepth=0.0, maxDepth=1.0) vk.vkCmdSetViewport(self.drawCmdBuffers[i], 0, 1, [viewport]) # Update dynamic scissor state offsetscissor = vk.VkOffset2D(x=0, y=0) extentscissor = vk.VkExtent2D(width=self.width, height=self.height) scissor = vk.VkRect2D(offset=offsetscissor, extent=extentscissor) vk.vkCmdSetScissor(self.drawCmdBuffers[i], 0, 1, [scissor]) self.scene.render(self.drawCmdBuffers[i], self.wireframe) #self.scene.render(self.drawCmdBuffers[i], True) self.drawUI(self.drawCmdBuffers[i]) vk.vkCmdEndRenderPass(self.drawCmdBuffers[i]) vk.vkEndCommandBuffer(self.drawCmdBuffers[i])
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()
def buildCommandBuffers(self): """ Build separate command buffers for every framebuffer image Unlike in OpenGL all rendering commands are recorded once into command buffers that are then resubmitted to the queue This allows to generate work upfront and from multiple threads, one of the biggest advantages of Vulkan """ cmdBufInfo = vk.VkCommandBufferBeginInfo( sType=vk.VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, pNext=None) # Set clear values for all framebuffer attachments with loadOp set to clear # We use two attachments (color and depth) that are cleared at the start of the subpass and as such we need to set clear values for both clearValues = [] clearValue = vk.VkClearValue(color=[[0.0, 0.0, 0.2, 1.0]]) clearValues.append(clearValue) clearValue = vk.VkClearValue(depthStencil=[1.0, 0]) clearValues.append(clearValue) offset = vk.VkOffset2D(x=0, y=0) extent = vk.VkExtent2D(width=self.width, height=self.height) renderArea = vk.VkRect2D(offset=offset, extent=extent) for i in range(len(self.drawCmdBuffers)): renderPassBeginInfo = vk.VkRenderPassBeginInfo( sType=vk.VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, pNext=None, renderPass=self.renderPass, renderArea=renderArea, clearValueCount=2, pClearValues=clearValues, # Set target frame buffer framebuffer=self.frameBuffers[i]) # wait this buffer to be released #vk.vkWaitForFences(self.device, 1, [self.waitFences[i]], vk.VK_TRUE, vk.UINT64_MAX) # rebuild this buffer vk.vkBeginCommandBuffer(self.drawCmdBuffers[i], cmdBufInfo) # Start the first sub pass specified in our default render pass setup by the base class # This will clear the color and depth attachment vk.vkCmdBeginRenderPass(self.drawCmdBuffers[i], renderPassBeginInfo, vk.VK_SUBPASS_CONTENTS_INLINE) # Update dynamic viewport state viewport = vk.VkViewport(height=float(self.height), width=float(self.width), minDepth=0.0, maxDepth=1.0) vk.vkCmdSetViewport(self.drawCmdBuffers[i], 0, 1, [viewport]) # Update dynamic scissor state offsetscissor = vk.VkOffset2D(x=0, y=0) extentscissor = vk.VkExtent2D(width=self.width, height=self.height) scissor = vk.VkRect2D(offset=offsetscissor, extent=extentscissor) vk.vkCmdSetScissor(self.drawCmdBuffers[i], 0, 1, [scissor]) # Bind descriptor sets describing shader binding points vk.vkCmdBindDescriptorSets(self.drawCmdBuffers[i], vk.VK_PIPELINE_BIND_POINT_GRAPHICS, self.pipelineLayout, 0, 1, [self.descriptorSet], 0, None) # Bind the rendering pipeline # The pipeline (state object) contains all states of the rendering pipeline, binding it will set all the states specified at pipeline creation time vk.vkCmdBindPipeline(self.drawCmdBuffers[i], vk.VK_PIPELINE_BIND_POINT_GRAPHICS, self.pipeline) # Bind triangle vertex buffer (contains position and colors) offsets = [0] vk.vkCmdBindVertexBuffers(self.drawCmdBuffers[i], 0, 1, [self.vertices['buffer']], offsets) # Bind triangle index buffer vk.vkCmdBindIndexBuffer(self.drawCmdBuffers[i], self.indices['buffer'], 0, vk.VK_INDEX_TYPE_UINT32) # Draw indexed triangle vk.vkCmdDrawIndexed(self.drawCmdBuffers[i], self.indices['count'], 1, 0, 0, 1) # uncomment for imgui support self.drawUI(self.drawCmdBuffers[i]) vk.vkCmdEndRenderPass(self.drawCmdBuffers[i]) # Ending the render pass will add an implicit barrier transitioning the frame buffer color attachment to # VK_IMAGE_LAYOUT_PRESENT_SRC_KHR for presenting it to the windowing system vk.vkEndCommandBuffer(self.drawCmdBuffers[i])