def _setup_objects(self): engine, api, device = self.ctx mem = engine.memory_manager scene = self.scene meshes = scene.meshes images = scene.images staging_mesh_offset = 0 data_meshes, data_objects, data_images, data_samplers = [], [], [], [] # Objects setup for obj in scene.objects: data_objects.append(DataGameObject(obj)) # Samplers for sampler in scene.samplers: data_samplers.append(DataSampler(engine, sampler)) # Meshes setup for mesh in meshes: data_mesh = DataMesh(mesh, staging_mesh_offset) data_meshes.append(data_mesh) staging_mesh_offset += mesh.size() # Images staging_image_offset = ( staging_mesh_offset + 256 ) & ~255 # staging_image_offset must be aligned to 256 bits for uploading purpose for image in images: data_image = DataImage(engine, image, staging_image_offset) data_images.append(data_image) staging_image_offset += image.size() if len(meshes) == 0 and len(images) == 0: staging_alloc = staging_buffer = meshes_alloc = meshes_buffer = images_alloc = None else: staging_alloc, staging_buffer = self._setup_objects_staging( staging_image_offset, data_meshes, data_images) meshes_alloc = meshes_buffer = images_alloc = None if len(meshes) > 0: meshes_alloc, meshes_buffer = self._setup_meshes_resources( staging_alloc, staging_buffer, staging_mesh_offset) if len(images) > 0: images_alloc = self._setup_images_resources( staging_alloc, staging_buffer, data_images) self.meshes_alloc = meshes_alloc self.meshes_buffer = meshes_buffer self.meshes = data_meshes self.images_alloc = images_alloc self.images = data_images self.samplers = data_samplers self.objects = data_objects if staging_buffer is not None: hvk.destroy_buffer(api, device, staging_buffer) mem.free_alloc(staging_alloc)
def clean_resources(): window.hide() hvk.device_wait_idle(api, device) hvk.destroy_fence(api, device, staging_fence) hvk.destroy_command_pool(api, device, staging_pool) hvk.destroy_command_pool(api, device, drawing_pool) hvk.destroy_buffer(api, device, mesh_buffer) hvk.free_memory(api, device, mesh_memory) hvk.destroy_sampler(api, device, texture_sampler) hvk.destroy_image_view(api, device, texture_view) hvk.destroy_image(api, device, texture_image) hvk.free_memory(api, device, texture_image_memory) hvk.destroy_descriptor_pool(api, device, descriptor_pool) hvk.destroy_buffer(api, device, uniforms_buffer) hvk.free_memory(api, device, uniforms_mem) hvk.destroy_pipeline(api, device, pipeline) hvk.destroy_pipeline_cache(api, device, pipeline_cache) hvk.destroy_pipeline_layout(api, device, pipeline_layout) for m in shader_modules: hvk.destroy_shader_module(api, device, m) hvk.destroy_descriptor_set_layout(api, device, descriptor_set_layout) for fb in framebuffers: hvk.destroy_framebuffer(api, device, fb) hvk.destroy_render_pass(api, device, render_pass) hvk.destroy_semaphore(api, device, image_ready) hvk.destroy_semaphore(api, device, rendering_done) for f in render_fences: hvk.destroy_fence(api, device, f) hvk.destroy_image(api, device, depth_stencil) hvk.destroy_image_view(api, device, depth_view) hvk.free_memory(api, device, depth_alloc) for v in swapchain_image_views: hvk.destroy_image_view(api, device, v) hvk.destroy_swapchain(api, device, swapchain) hvk.destroy_device(api, device) hvk.destroy_surface(api, instance, surface) debugger.stop() hvk.destroy_instance(api, instance) window.destroy()
def free(self): engine, api, device = self.ctx mem = engine.memory_manager if self.uniforms_alloc is not None: hvk.destroy_buffer(api, device, self.uniforms_buffer) mem.free_alloc(self.uniforms_alloc) if self.descriptor_pool is not None: hvk.destroy_descriptor_pool(api, device, self.descriptor_pool) for pipeline in self.pipelines: hvk.destroy_pipeline(api, device, pipeline) for pipeline in self.compute_pipelines: hvk.destroy_pipeline(api, device, pipeline) hvk.destroy_pipeline_cache(api, device, self.pipeline_cache) if self.meshes_buffer is not None: hvk.destroy_buffer(api, device, self.meshes_buffer) mem.free_alloc(self.meshes_alloc) for sampler in self.samplers: sampler.free() for img in self.images: for view in img.views.values(): hvk.destroy_image_view(api, device, view) img.free() if self.images_alloc is not None: mem.free_alloc(self.images_alloc) for compute in self.computes: compute.free() for shader in self.shaders: shader.free() hvk.destroy_command_pool(api, device, self.command_pool) for _, pool in self.compute_pools: hvk.destroy_command_pool(api, device, pool) # Make it easier for python to deal with the circular dependencies del self.engine del self.scene del self.shaders
def mesh_to_device(): global mesh_buffer, mesh_memory, staging_mesh_buffer, staging_mesh_memory, mesh_data # Create mesh resources mesh_buffer = hvk.create_buffer( api, device, hvk.buffer_create_info(size=total_mesh_size, usage=vk.BUFFER_USAGE_TRANSFER_DST_BIT | vk.BUFFER_USAGE_INDEX_BUFFER_BIT | vk.BUFFER_USAGE_VERTEX_BUFFER_BIT)) mesh_req = hvk.buffer_memory_requirements(api, device, mesh_buffer) mt_index = find_memory_type(vk.MEMORY_HEAP_DEVICE_LOCAL_BIT, vk.MEMORY_PROPERTY_DEVICE_LOCAL_BIT) mesh_memory = hvk.allocate_memory( api, device, hvk.memory_allocate_info(allocation_size=mesh_req.size, memory_type_index=mt_index)) hvk.bind_buffer_memory(api, device, mesh_buffer, mesh_memory, 0) # Upload mesh to device memory (recording) hvk.begin_command_buffer(api, staging_cmd, hvk.command_buffer_begin_info()) region = vk.BufferCopy(src_offset=0, dst_offset=0, size=mesh_req.size) hvk.copy_buffer(api, staging_cmd, staging_mesh_buffer, mesh_buffer, (region, )) hvk.end_command_buffer(api, staging_cmd) # Upload mesh to device memory (submiting) submit_info = hvk.submit_info(command_buffers=(staging_cmd, )) hvk.queue_submit(api, render_queue.handle, (submit_info, ), fence=staging_fence) hvk.wait_for_fences(api, device, (staging_fence, )) # Free staging resources hvk.destroy_buffer(api, device, staging_mesh_buffer) hvk.free_memory(api, device, staging_mesh_memory) del mesh_data, staging_mesh_buffer, staging_mesh_memory
def texture_to_device(): global texture_image, texture_image_memory, texture_image_layout, texture_view, texture_sampler global texture, staging_texture_buffer, staging_texture_memory # Create the vulkan image texture_image_layout = vk.IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL texture_image = hvk.create_image( api, device, hvk.image_create_info( format=texture.format, mip_levels=len(texture.mipmaps), extent=vk.Extent3D(texture.width, texture.height, texture.depth), usage=vk.IMAGE_USAGE_TRANSFER_DST_BIT | vk.IMAGE_USAGE_SAMPLED_BIT, )) img_req = hvk.image_memory_requirements(api, device, texture_image) mt_index = find_memory_type(vk.MEMORY_HEAP_DEVICE_LOCAL_BIT, vk.MEMORY_HEAP_DEVICE_LOCAL_BIT) texture_image_memory = hvk.allocate_memory( api, device, hvk.memory_allocate_info(allocation_size=img_req.size, memory_type_index=mt_index)) hvk.bind_image_memory(api, device, texture_image, texture_image_memory, 0) # Build the copy regions (1 for each mipmap) regions = [] for i, m in enumerate(texture.mipmaps): region = hvk.buffer_image_copy( image_subresource=hvk.image_subresource_layers(mip_level=i), image_extent=vk.Extent3D(m.width, m.height, 1), buffer_offset=m.offset) regions.append(region) # Build the image barrier for the image layout transitions barrier = hvk.image_memory_barrier( image=texture_image, new_layout=0, dst_access_mask=0, subresource_range=hvk.image_subresource_range( level_count=len(texture.mipmaps))) # Transfer the staging data to device hvk.begin_command_buffer(api, staging_cmd, hvk.command_buffer_begin_info()) barrier.new_layout = vk.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL barrier.dst_access_mask = vk.ACCESS_TRANSFER_WRITE_BIT hvk.pipeline_barrier(api, staging_cmd, (barrier, ), dst_stage_mask=vk.PIPELINE_STAGE_TRANSFER_BIT) hvk.copy_buffer_to_image(api, staging_cmd, staging_texture_buffer, texture_image, vk.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, regions) barrier.old_layout = vk.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL barrier.new_layout = vk.IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL barrier.src_access_mask = vk.ACCESS_TRANSFER_WRITE_BIT barrier.dst_access_mask = vk.ACCESS_SHADER_READ_BIT hvk.pipeline_barrier(api, staging_cmd, (barrier, ), dst_stage_mask=vk.PIPELINE_STAGE_FRAGMENT_SHADER_BIT) hvk.end_command_buffer(api, staging_cmd) # Submit the staging command buffer hvk.reset_fences(api, device, (staging_fence, )) submit_info = hvk.submit_info(command_buffers=(staging_cmd, )) hvk.queue_submit(api, render_queue.handle, (submit_info, ), fence=staging_fence) hvk.wait_for_fences(api, device, (staging_fence, )) # Create the image view and the sampler texture_view = hvk.create_image_view( api, device, hvk.image_view_create_info( image=texture_image, format=texture.format, subresource_range=hvk.image_subresource_range( level_count=len(texture.mipmaps)))) texture_sampler = hvk.create_sampler( api, device, hvk.sampler_create_info( mag_filter=vk.FILTER_LINEAR, min_filter=vk.FILTER_LINEAR, max_lod=len(texture.mipmaps), )) # Free staging resources hvk.destroy_buffer(api, device, staging_texture_buffer) hvk.free_memory(api, device, staging_texture_memory) del texture, staging_texture_buffer, staging_texture_memory