Created
October 9, 2018 13:45
-
-
Save Dooskington/8f09e560735ee3efa296f6bdef8338e0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Create texture | |
let (texture_image, texture_memory, texture_view, texture_sampler) = { | |
let img = image::open("res/textures/costanza.png") | |
.expect("Failed to load image!") | |
.to_rgba(); | |
let (width, height) = img.dimensions(); | |
let (texture_image, texture_memory, texture_view) = create_image( | |
&device, | |
physical_device, | |
width, | |
height, | |
Format::Rgba8Srgb, | |
img::Usage::TRANSFER_DST | img::Usage::SAMPLED, | |
Aspects::COLOR); | |
let texture_sampler = device.create_sampler(img::SamplerInfo::new(Filter::Linear, WrapMode::Tile)); | |
// Write data into texture | |
{ | |
let row_alignment_mask = | |
physical_device.limits().min_buffer_copy_pitch_alignment as u32 - 1; | |
let image_stride: usize = 4; | |
let row_pitch = | |
(width * image_stride as u32 + row_alignment_mask) & !row_alignment_mask; | |
let upload_size: u64 = (height * row_pitch).into(); | |
let (image_upload_buffer, mut image_upload_memory) = create_buffer( | |
&device, | |
physical_device, | |
buffer::Usage::TRANSFER_SRC, | |
Properties::CPU_VISIBLE, | |
upload_size, | |
); | |
{ | |
let mut data = device | |
.acquire_mapping_writer::<u8>(&image_upload_memory, 0..upload_size) | |
.unwrap(); | |
for y in 0..height as usize { | |
let row = &(*img)[y * (width as usize) * image_stride | |
..(y + 1) * (width as usize) * image_stride]; | |
let dest_base = y * row_pitch as usize; | |
data[dest_base..dest_base + row.len()].copy_from_slice(row); | |
} | |
device.release_mapping_writer(data); | |
} | |
// Submit commands to transfer data | |
let submit = { | |
let mut cmd_buffer = command_pool.acquire_command_buffer(false); | |
let image_barrier = Barrier::Image { | |
states: (Access::empty(), Layout::Undefined) | |
..(Access::TRANSFER_WRITE, Layout::TransferDstOptimal), | |
target: &texture_image, | |
range: SubresourceRange { | |
aspects: Aspects::COLOR, | |
levels: 0..1, | |
layers: 0..1, | |
}, | |
}; | |
cmd_buffer.pipeline_barrier( | |
PipelineStage::TOP_OF_PIPE..PipelineStage::TRANSFER, | |
Dependencies::empty(), | |
&[image_barrier] | |
); | |
cmd_buffer.copy_buffer_to_image( | |
&image_upload_buffer, | |
&texture_image, | |
Layout::TransferDstOptimal, | |
&[BufferImageCopy { | |
buffer_offset: 0, | |
buffer_width: row_pitch / (image_stride as u32), | |
buffer_height: height as u32, | |
image_layers: SubresourceLayers { | |
aspects: Aspects::COLOR, | |
level: 0, | |
layers: 0..1, | |
}, | |
image_offset: Offset { x: 0, y: 0, z: 0 }, | |
image_extent: Extent { width, height, depth: 1 }, | |
}], | |
); | |
let image_barrier = Barrier::Image { | |
states: (Access::TRANSFER_WRITE, Layout::TransferDstOptimal) | |
..(Access::SHADER_READ, Layout::ShaderReadOnlyOptimal), | |
target: &texture_image, | |
range: SubresourceRange { | |
aspects: Aspects::COLOR, | |
levels: 0..1, | |
layers: 0..1, | |
}, | |
}; | |
cmd_buffer.pipeline_barrier( | |
PipelineStage::TRANSFER..PipelineStage::FRAGMENT_SHADER, | |
Dependencies::empty(), | |
&[image_barrier], | |
); | |
cmd_buffer.finish() | |
}; | |
let submission = Submission::new().submit(Some(submit)); | |
queue_group.queues[0].submit(submission, Some(&frame_fence)); | |
device.wait_for_fence(&frame_fence, !0); | |
// Destroy our staging resources | |
device.destroy_buffer(image_upload_buffer); | |
device.free_memory(image_upload_memory); | |
} | |
(texture_image, texture_memory, texture_view, texture_sampler) | |
}; | |
fn create_image( | |
device: &impl Device<backend::Backend>, | |
physical_device: &PhysicalDevice<backend::Backend>, | |
width: u32, | |
height: u32, | |
format: Format, | |
usage: img::Usage, | |
aspects: Aspects, | |
) -> (GfxImage, GfxMemory, GfxImageView) { | |
// Get a list of available memory types | |
let memory_types = physical_device.memory_properties().memory_types; | |
let kind = img::Kind::D2(width, height, 1, 1); | |
let unbound_image = device | |
.create_image( | |
kind, | |
1, | |
format, | |
img::Tiling::Optimal, | |
usage, | |
ViewCapabilities::empty(), | |
).expect("Failed to create unbound image!"); | |
let requirements = device.get_image_requirements(&unbound_image); | |
let device_type = memory_types | |
.iter() | |
.enumerate() | |
.position(|(id, memory_type)| { | |
requirements.type_mask & (1_u64 << id) != 0 | |
&& memory_type.properties.contains(Properties::DEVICE_LOCAL) | |
}).unwrap() | |
.into(); | |
let image_memory = device | |
.allocate_memory(device_type, requirements.size) | |
.expect("Failed to allocate image memory!"); | |
let image = device | |
.bind_image_memory(&image_memory, 0, unbound_image) | |
.expect("Failed to bind image memory!"); | |
let image_view = device | |
.create_image_view( | |
&image, | |
img::ViewKind::D2, | |
format, | |
Swizzle::NO, | |
img::SubresourceRange { | |
aspects, | |
levels: 0..1, | |
layers: 0..1, | |
}, | |
).expect("Failed to create image view!"); | |
(image, image_memory, image_view) | |
} | |
fn create_buffer( | |
device: &impl Device<backend::Backend>, | |
physical_device: &PhysicalDevice<backend::Backend>, | |
usage: buffer::Usage, | |
properties: Properties, | |
buffer_len: u64, | |
) -> (GfxBuffer, GfxMemory) { | |
// Get a list of available memory types | |
let memory_types = physical_device.memory_properties().memory_types; | |
// First create an unbound buffer | |
let unbound_buffer = device.create_buffer(buffer_len, usage).unwrap(); | |
// Get the memory requirements for this buffer | |
let mem_requirements = device.get_buffer_requirements(&unbound_buffer); | |
// Filter through memory types to find one that is appropriate. | |
let upload_type = memory_types | |
.iter() | |
.enumerate() | |
.find(|(id, ty)| { | |
let type_supported = mem_requirements.type_mask & (1_u64 << id) != 0; | |
type_supported && ty.properties.contains(properties) | |
}) | |
.map(|(id, _ty)| MemoryTypeId(id)) | |
.expect("Could not find appropriate vertex buffer memory type!"); | |
// Now allocate the memory and bind our buffer to it. | |
let buffer_memory = device | |
.allocate_memory(upload_type, mem_requirements.size) | |
.unwrap(); | |
let buffer = device | |
.bind_buffer_memory(&buffer_memory, 0, unbound_buffer) | |
.unwrap(); | |
(buffer, buffer_memory) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment