sim2d/streaming_renderer/texture/
mod.rs1mod atlas;
2mod loader;
3
4use {
5 anyhow::{Context, Result},
6 ash::vk,
7 demo_vk::graphics::vulkan::{OwnedBlock, VulkanContext, raii},
8};
9
10pub use self::{atlas::TextureAtlas, loader::TextureLoader};
11
12pub struct Texture {
20 mip_levels: u32,
21 width: u32,
22 height: u32,
23 image_view: raii::ImageView,
24 image: raii::Image,
25 block: OwnedBlock,
26}
27
28#[bon::bon]
29impl Texture {
30 #[builder]
31 pub fn new(
32 ctx: &VulkanContext,
33 dimensions: (u32, u32),
34 format: vk::Format,
35 image_usage_flags: vk::ImageUsageFlags,
36 memory_property_flags: vk::MemoryPropertyFlags,
37 #[builder(default = 1)] mip_levels: u32,
38 ) -> Result<Self> {
39 let (width, height) = dimensions;
40
41 let (block, image) = OwnedBlock::allocate_image(
42 ctx.allocator.clone(),
43 &vk::ImageCreateInfo {
44 flags: vk::ImageCreateFlags::empty(),
45 image_type: vk::ImageType::TYPE_2D,
46 format,
47 extent: vk::Extent3D {
48 width,
49 height,
50 depth: 1,
51 },
52 mip_levels,
53 array_layers: 1,
54 samples: vk::SampleCountFlags::TYPE_1,
55 tiling: vk::ImageTiling::OPTIMAL,
56 usage: image_usage_flags,
57 sharing_mode: vk::SharingMode::EXCLUSIVE,
58 queue_family_index_count: 1,
59 p_queue_family_indices: &ctx.graphics_queue_family_index,
60 initial_layout: vk::ImageLayout::UNDEFINED,
61 ..Default::default()
62 },
63 memory_property_flags,
64 )
65 .context("Unable to create texture image!")?;
66
67 let is_depth = image_usage_flags
68 .contains(vk::ImageUsageFlags::DEPTH_STENCIL_ATTACHMENT);
69 let image_view = raii::ImageView::new(
70 "Texture Image View",
71 ctx.device.clone(),
72 &vk::ImageViewCreateInfo {
73 image: image.raw,
74 view_type: vk::ImageViewType::TYPE_2D,
75 format,
76 components: vk::ComponentMapping::default(),
77 subresource_range: vk::ImageSubresourceRange {
78 aspect_mask: if is_depth {
79 vk::ImageAspectFlags::DEPTH
80 } else {
81 vk::ImageAspectFlags::COLOR
82 },
83 base_mip_level: 0,
84 level_count: mip_levels,
85 base_array_layer: 0,
86 layer_count: 1,
87 },
88 ..Default::default()
89 },
90 )
91 .context("Unable to create texture image view")?;
92
93 Ok(Self {
94 mip_levels,
95 width,
96 height,
97 image_view,
98 image,
99 block,
100 })
101 }
102
103 pub fn image(&self) -> &raii::Image {
105 &self.image
106 }
107
108 pub fn view(&self) -> &raii::ImageView {
110 &self.image_view
111 }
112
113 pub fn memory(&self) -> &OwnedBlock {
115 &self.block
116 }
117
118 pub fn width(&self) -> u32 {
119 self.width
120 }
121
122 pub fn height(&self) -> u32 {
123 self.height
124 }
125
126 pub fn extent(&self) -> vk::Extent2D {
127 vk::Extent2D {
128 width: self.width,
129 height: self.height,
130 }
131 }
132
133 #[builder]
134 pub fn pipeline_barrier(
135 &self,
136 ctx: &VulkanContext,
137 command_buffer: vk::CommandBuffer,
138 old_layout: vk::ImageLayout,
139 new_layout: vk::ImageLayout,
140 src_access_mask: vk::AccessFlags,
141 dst_access_mask: vk::AccessFlags,
142 src_stage_mask: vk::PipelineStageFlags,
143 dst_stage_mask: vk::PipelineStageFlags,
144 ) {
145 let is_depth_texture = dst_access_mask
146 .contains(vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ)
147 || dst_access_mask
148 .contains(vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE);
149
150 let image_memory_barrier = vk::ImageMemoryBarrier {
151 old_layout,
152 new_layout,
153 src_access_mask,
154 dst_access_mask,
155 image: self.image.raw,
156 subresource_range: vk::ImageSubresourceRange {
157 aspect_mask: if is_depth_texture {
158 vk::ImageAspectFlags::DEPTH
159 } else {
160 vk::ImageAspectFlags::COLOR
161 },
162 base_mip_level: 0,
163 level_count: self.mip_levels,
164 base_array_layer: 0,
165 layer_count: 1,
166 },
167 ..Default::default()
168 };
169 unsafe {
170 ctx.cmd_pipeline_barrier(
171 command_buffer,
172 src_stage_mask,
173 dst_stage_mask,
174 vk::DependencyFlags::empty(),
175 &[],
176 &[],
177 &[image_memory_barrier],
178 );
179 }
180 }
181}