use narcissus_gpu::{
create_device, Access, BufferDesc, BufferImageCopy, BufferUsageFlags, ClearValue, Extent2d,
Extent3d, ImageAspectFlags, ImageBarrier, ImageDesc, ImageDimension, ImageFormat, ImageLayout,
- ImageUsageFlags, LoadOp, MemoryLocation, Offset2d, Offset3d, RenderingAttachment,
+ ImageTiling, ImageUsageFlags, LoadOp, MemoryLocation, Offset2d, Offset3d, RenderingAttachment,
RenderingDesc, Scissor, StoreOp, ThreadToken, Viewport,
};
use narcissus_maths::{sin_cos_pi_f32, vec3, Affine3, HalfTurn, Mat3, Mat4, Point3, Vec3};
usage: ImageUsageFlags::SAMPLED | ImageUsageFlags::TRANSFER,
dimension: ImageDimension::Type2d,
format: ImageFormat::RGBA8_SRGB,
- initial_layout: ImageLayout::Optimal,
+ tiling: ImageTiling::Optimal,
width: blåhaj_image_data.width() as u32,
height: blåhaj_image_data.height() as u32,
depth: 1,
host_mapped: false,
dimension: ImageDimension::Type2d,
format: ImageFormat::R8_UNORM,
- initial_layout: ImageLayout::Optimal,
+ tiling: ImageTiling::Optimal,
width: glyph_cache.width() as u32,
height: glyph_cache.height() as u32,
depth: 1,
usage: ImageUsageFlags::DEPTH_STENCIL_ATTACHMENT,
dimension: ImageDimension::Type2d,
format: ImageFormat::DEPTH_F32,
- initial_layout: ImageLayout::Optimal,
+ tiling: ImageTiling::Optimal,
width,
height,
depth: 1,
pub struct VulkanMemoryType {
tlsf: Mutex<Tlsf>,
- /// Tlsf instance used exclusively for images when the
- tlsf_images: Mutex<Tlsf>,
+ /// Tlsf instance used exclusively for non-linear images when the
+ /// `buffer_image_granularity` limit is greater than the minimum alignment
+ /// guaranteed by the current Tlsf configuration.
+ tlsf_non_linear: Mutex<Tlsf>,
}
#[derive(Default)]
memory_heaps: [VulkanMemoryHeap; vk::MAX_MEMORY_HEAPS as usize],
memory_types: [VulkanMemoryType; vk::MAX_MEMORY_TYPES as usize],
dedicated: Mutex<HashSet<vk::DeviceMemory>>,
- use_segregated_image_allocator: bool,
+ use_segregated_non_linear_allocator: bool,
allocation_count: AtomicU32,
}
Self {
memory_heaps,
- use_segregated_image_allocator,
+ use_segregated_non_linear_allocator: use_segregated_image_allocator,
..default()
}
}
pub struct VulkanSuperBlockInfo {
memory: vk::DeviceMemory,
mapped_ptr: *mut u8,
- image_allocator: bool,
+ non_linear: bool,
memory_type_index: u32,
}
VulkanMemory::SubAlloc(sub_alloc) => {
let user_data = sub_alloc.allocation.user_data();
let memory_type = &self.allocator.memory_types[user_data.memory_type_index.widen()];
- let mut tlsf = if user_data.image_allocator {
- memory_type.tlsf_images.lock()
+ let mut tlsf = if user_data.non_linear {
+ memory_type.tlsf_non_linear.lock()
} else {
memory_type.tlsf.lock()
};
pub fn allocate_memory(
&self,
memory_location: MemoryLocation,
+ non_linear: bool,
host_mapped: bool,
resource: VulkanAllocationResource,
) -> VulkanMemory {
..default()
};
- let (is_image_allocation, memory_dedicated_allocate_info) = match resource {
+ let memory_dedicated_allocate_info = match resource {
// SAFETY: Safe so long as `_next` on `memory_requirements` is valid.
VulkanAllocationResource::Buffer(buffer) => unsafe {
self.device_fn.get_buffer_memory_requirements2(
},
&mut memory_requirements,
);
- (
- false,
- vk::MemoryDedicatedAllocateInfo {
- buffer,
- ..default()
- },
- )
+ vk::MemoryDedicatedAllocateInfo {
+ buffer,
+ ..default()
+ }
},
// SAFETY: Safe so long as `_next` on `memory_requirements` is valid.
VulkanAllocationResource::Image(image) => unsafe {
&vk::ImageMemoryRequirementsInfo2 { image, ..default() },
&mut memory_requirements,
);
- (true, vk::MemoryDedicatedAllocateInfo { image, ..default() })
+ vk::MemoryDedicatedAllocateInfo { image, ..default() }
},
};
// If the allocation is smaller than the Tlsf super-block size for this
// allocation type, we should attempt sub-allocation.
if size <= memory_heap.tlsf_super_block_size {
- let (image_allocator, mut tlsf) = if (VULKAN_CONSTANTS
- .tlsf_force_segregated_image_allocator
- || self.allocator.use_segregated_image_allocator)
- && is_image_allocation
+ let (non_linear, mut tlsf) = if (VULKAN_CONSTANTS
+ .tlsf_force_segregated_non_linear_allocator
+ || self.allocator.use_segregated_non_linear_allocator)
+ && non_linear
{
- (true, memory_type.tlsf_images.lock())
+ (true, memory_type.tlsf_non_linear.lock())
} else {
(false, memory_type.tlsf.lock())
};
VulkanSuperBlockInfo {
memory,
mapped_ptr,
- image_allocator,
+ // `non_linear` is only true here if we're allocating in the `tlsf_non_linear`
+ // allocator, *not* if the resource we're allocating for is non-linear.
+ non_linear,
memory_type_index: memory_type_index as u32,
},
);
.free_memory(self.device, super_block.user_data.memory, None)
}
}
- for super_block in memory_type.tlsf_images.get_mut().super_blocks() {
+ for super_block in memory_type.tlsf_non_linear.get_mut().super_blocks() {
unsafe {
self.device_fn
.free_memory(self.device, super_block.user_data.memory, None)
use crate::{
BindingType, BlendMode, BufferUsageFlags, ClearValue, CompareOp, CullingMode, FrontFace,
ImageAspectFlags, ImageDimension, ImageFormat, ImageSubresourceLayers, ImageSubresourceRange,
- IndexType, LoadOp, PolygonMode, ShaderStageFlags, StencilOp, StencilOpState, StoreOp, Topology,
+ ImageTiling, IndexType, LoadOp, PolygonMode, ShaderStageFlags, StencilOp, StencilOpState,
+ StoreOp, Topology,
};
#[must_use]
layer_count: subresource.array_layer_count,
}
}
+
+pub fn vulkan_image_tiling(tiling: ImageTiling) -> vk::ImageTiling {
+ match tiling {
+ ImageTiling::Linear => vk::ImageTiling::LINEAR,
+ ImageTiling::Optimal => vk::ImageTiling::OPTIMAL,
+ }
+}
BindGroupLayoutDesc, Buffer, BufferArg, BufferDesc, BufferImageCopy, BufferUsageFlags,
CmdBuffer, ComputePipelineDesc, Device, Extent2d, Extent3d, Frame, GlobalBarrier,
GpuConcurrent, GraphicsPipelineDesc, Image, ImageBarrier, ImageBlit, ImageDesc, ImageDimension,
- ImageFormat, ImageLayout, ImageUsageFlags, ImageViewDesc, IndexType, MemoryLocation, Offset2d,
- Offset3d, Pipeline, Sampler, SamplerAddressMode, SamplerCompareOp, SamplerDesc, SamplerFilter,
- SwapchainOutOfDateError, ThreadToken, TransientBuffer, TypedBind,
+ ImageFormat, ImageLayout, ImageTiling, ImageUsageFlags, ImageViewDesc, IndexType,
+ MemoryLocation, Offset2d, Offset3d, Pipeline, Sampler, SamplerAddressMode, SamplerCompareOp,
+ SamplerDesc, SamplerFilter, SwapchainOutOfDateError, ThreadToken, TransientBuffer, TypedBind,
};
mod allocator;
/// `tlsf_small_super_block_divisor` as the super block size.
tlsf_small_super_block_divisor: u64,
- /// Force use of separate allocators for images and buffers.
- tlsf_force_segregated_image_allocator: bool,
+ /// Force use of separate allocators for optimal tiling images and buffers.
+ tlsf_force_segregated_non_linear_allocator: bool,
/// The max number of descriptor sets allocatable from each descriptor pool.
descriptor_pool_max_sets: u32,
transient_buffer_size: 4 * 1024 * 1024,
tlsf_default_super_block_size: 128 * 1024 * 1024,
tlsf_small_super_block_divisor: 16,
- tlsf_force_segregated_image_allocator: false,
+ tlsf_force_segregated_non_linear_allocator: false,
descriptor_pool_max_sets: 500,
descriptor_pool_sampler_count: 100,
descriptor_pool_uniform_buffer_count: 500,
let memory = self.allocate_memory(
desc.memory_location,
+ false,
desc.host_mapped,
allocator::VulkanAllocationResource::Buffer(buffer),
);
depth: desc.depth,
};
+ let tiling = vulkan_image_tiling(desc.tiling);
+
let mut usage = default();
if desc.usage.contains(ImageUsageFlags::SAMPLED) {
usage |= vk::ImageUsageFlags::SAMPLED;
mip_levels: desc.mip_levels,
array_layers: desc.layer_count,
samples: vk::SampleCountFlags::SAMPLE_COUNT_1,
- tiling: vk::ImageTiling::OPTIMAL,
+ tiling,
usage,
sharing_mode: vk::SharingMode::Exclusive,
queue_family_indices: queue_family_indices.into(),
let memory = self.allocate_memory(
desc.memory_location,
+ desc.tiling == ImageTiling::Optimal,
desc.host_mapped,
allocator::VulkanAllocationResource::Image(image),
);
let memory = self.allocate_memory(
MemoryLocation::Host,
+ false,
true,
allocator::VulkanAllocationResource::Buffer(buffer),
);
let memory = self.allocate_memory(
MemoryLocation::Host,
+ false,
true,
allocator::VulkanAllocationResource::Buffer(buffer),
);
pub usage: ImageUsageFlags,
pub dimension: ImageDimension,
pub format: ImageFormat,
- pub initial_layout: ImageLayout,
+ pub tiling: ImageTiling,
pub width: u32,
pub height: u32,
pub depth: u32,
General,
}
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub enum ImageTiling {
+ Linear,
+ Optimal,
+}
+
pub struct GlobalBarrier<'a> {
pub prev_access: &'a [Access],
pub next_access: &'a [Access],