def from_uncompressed(cls, data, **kwargs): keys = tuple(kwargs.keys()) if ("format" not in keys) or ("extent" not in keys): raise ValueError( "Image `format` and `extent` must be specified as keyword arguments" ) if kwargs.get("no_default_view", False) == False and ("default_view_type" not in keys): raise ValueError( "If a default image view is generated, `default_view_type` must be specified as a keyword argument" ) image = super().__new__(cls) image.__init__(**kwargs) image.source_type = ImageSource.Uncompressed image.source = data image.flags = kwargs.get('flags', 0) image.format = kwargs["format"] image.extent = kwargs["extent"] image.mipmaps_levels = 1 image.texture_size = len(data) image.array_layers = 1 if kwargs.get("no_default_view", False) != True: subs_range = hvk.image_subresource_range( level_count=image.mipmaps_levels, layer_count=image.array_layers) image.views["default"] = ImageView.from_params( view_type=kwargs["default_view_type"], format=image.format, subresource_range=subs_range) return image
def from_ktx(cls, ktx_file, **kwargs): f = ktx_file if not isinstance(f, KTXFile): raise RuntimeError( f"File must be KTXFile, got {type(f).__qualname__}") image = super().__new__(cls) image.__init__(**kwargs) image.source_type = ImageSource.Ktx image.source = f image.flags = f.vk_flags image.format = f.vk_format image.extent = (f.width, f.height, f.depth) image.mipmaps_levels = f.mips_level image.texture_size = f.texture_size image.array_layers = f.faces * f.array_element if kwargs.get("no_default_view", False) != True: subs_range = hvk.image_subresource_range( level_count=f.mips_level, layer_count=image.array_layers) image.views["default"] = ImageView.from_params( view_type=f.vk_view_type, format=f.vk_format, subresource_range=subs_range) return image
def _setup_depth_stencil(self): engine, api, device = self.ctx width, height = engine.info["swapchain_extent"].values() depth_format = engine.info["depth_format"] mem = engine.memory_manager if self.depth_stencil is not None: hvk.destroy_image_view(api, device, self.depth_stencil.view) hvk.destroy_image(api, device, self.depth_stencil.image) mem.free_alloc(self.depth_stencil_alloc) depth_stencil_image = hvk.create_image( api, device, hvk.image_create_info( format=depth_format, extent=vk.Extent3D(width=width, height=height, depth=1), usage=vk.IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) alloc = mem.alloc(depth_stencil_image, vk.STRUCTURE_TYPE_IMAGE_CREATE_INFO, types=(vk.MEMORY_PROPERTY_DEVICE_LOCAL_BIT, )) depth_stencil_view = hvk.create_image_view( api, device, hvk.image_view_create_info( image=depth_stencil_image, format=depth_format, subresource_range=hvk.image_subresource_range( aspect_mask=vk.IMAGE_ASPECT_DEPTH_BIT | vk.IMAGE_ASPECT_STENCIL_BIT))) self.depth_stencil = ImageAndView(image=depth_stencil_image, view=depth_stencil_view) self.depth_stencil_alloc = alloc
def __init__(self, **kw): self.params = dict(view_type=kw.get('view_type', vk.IMAGE_VIEW_TYPE_2D), format=kw['format'], components=kw.get('components', hvk.component_mapping()), subresource_range=kw.get( 'subresource_range', hvk.image_subresource_range()))
def setup_swapchain_depth_stencil(recreate=False): global depth_format, depth_stencil, depth_alloc, depth_view if recreate: hvk.destroy_image_view(api, device, depth_view) hvk.destroy_image(api, device, depth_stencil) hvk.free_memory(api, device, depth_alloc) width, height = window.dimensions() # Depth stencil attachment setup depth_format = None depth_formats = (vk.FORMAT_D32_SFLOAT_S8_UINT, vk.FORMAT_D24_UNORM_S8_UINT, vk.FORMAT_D16_UNORM_S8_UINT) for fmt in depth_formats: prop = hvk.physical_device_format_properties(api, physical_device, fmt) if IntFlag(vk.FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) in IntFlag( prop.optimal_tiling_features): depth_format = fmt break if depth_format is None: raise RuntimeError("Failed to find a suitable depth stencil format.") # Depth stencil image creation depth_stencil = hvk.create_image( api, device, hvk.image_create_info(format=depth_format, extent=vk.Extent3D(width=width, height=height, depth=1), usage=vk.IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | vk.IMAGE_USAGE_TRANSFER_SRC_BIT)) # Depth stencil image memory image_memreq = hvk.image_memory_requirements(api, device, depth_stencil) mt_index = find_memory_type(vk.MEMORY_HEAP_DEVICE_LOCAL_BIT, vk.MEMORY_PROPERTY_DEVICE_LOCAL_BIT) depth_stencil_size = image_memreq.size * 2 depth_alloc = hvk.allocate_memory( api, device, hvk.memory_allocate_info(allocation_size=depth_stencil_size, memory_type_index=mt_index)) hvk.bind_image_memory(api, device, depth_stencil, depth_alloc) # Depth stencil image view depth_view = hvk.create_image_view( api, device, hvk.image_view_create_info( image=depth_stencil, format=depth_format, subresource_range=hvk.image_subresource_range( aspect_mask=vk.IMAGE_ASPECT_DEPTH_BIT | vk.IMAGE_ASPECT_STENCIL_BIT)))
def device_update_image_layout(api, cmd_buffer, queue, cmd_data, data_scene): data_image = data_scene.images[cmd_data["image_id"]] image = data_image.image data_image.update_layout(cmd_data["new_layout"]) queue_flags = queue.family.properties.queue_flags dst_stage_mask = hvk.dst_stage_mask_for_access_mask( data_image.target_access_mask, queue_flags=queue_flags) change_layout = hvk.image_memory_barrier( image=data_image.image_handle, old_layout=data_image.layout, new_layout=data_image.target_layout, src_access_mask=data_image.access_mask, dst_access_mask=data_image.target_access_mask, subresource_range=hvk.image_subresource_range( level_count=image.mipmaps_levels, layer_count=image.array_layers)) hvk.pipeline_barrier(api, cmd_buffer, (change_layout, ), dst_stage_mask=dst_stage_mask)
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
def _setup_image_layouts(self, staging_buffer, data_images): engine, api, device = self.ctx to_transfer = hvk.image_memory_barrier( image=0, new_layout=vk.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, dst_access_mask=vk.ACCESS_TRANSFER_WRITE_BIT, subresource_range=hvk.image_subresource_range(level_count=0)) to_final_layout = hvk.image_memory_barrier( image=0, old_layout=vk.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, new_layout=0, src_access_mask=vk.ACCESS_TRANSFER_WRITE_BIT, dst_access_mask=0, subresource_range=hvk.image_subresource_range(level_count=0)) cmd = engine.setup_command_buffer hvk.begin_command_buffer(api, cmd, hvk.command_buffer_begin_info()) for data_image in data_images: image = data_image.image image_handle = data_image.image_handle regions = [] for m in image.iter_mipmaps(): r = hvk.buffer_image_copy( image_subresource=hvk.image_subresource_layers( mip_level=m.level, base_array_layer=m.layer), image_extent=vk.Extent3D(m.width, m.height, 1), buffer_offset=data_image.base_staging_offset + m.offset) regions.append(r) to_transfer.image = image_handle to_transfer.subresource_range.level_count = image.mipmaps_levels to_transfer.subresource_range.layer_count = image.array_layers to_final_layout.image = image_handle to_final_layout.new_layout = data_image.target_layout to_final_layout.dst_access_mask = data_image.target_access_mask to_final_layout.subresource_range.level_count = image.mipmaps_levels to_final_layout.subresource_range.layer_count = image.array_layers hvk.pipeline_barrier(api, cmd, (to_transfer, ), dst_stage_mask=vk.PIPELINE_STAGE_TRANSFER_BIT) hvk.copy_buffer_to_image(api, cmd, staging_buffer, image_handle, vk.IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, regions) hvk.pipeline_barrier( api, cmd, (to_final_layout, ), dst_stage_mask=hvk.dst_stage_mask_for_access_mask( to_final_layout.dst_access_mask)) hvk.end_command_buffer(api, cmd) # Sumbit the images and update the layer values in the images engine.submit_setup_command(wait=True) for img in data_images: img.layout = img.target_layout img.access_mask = img.target_access_mask