vk: implement framebuffer operations (gen_mips/copy/clear)
This commit is contained in:
parent
23458917f3
commit
a34bdccc06
4 changed files with 326 additions and 29 deletions
|
@ -70,9 +70,13 @@ impl FramebufferInterface for Gl3Framebuffer {
|
||||||
.size
|
.size
|
||||||
.scale_viewport(scaling, viewport.output.size);
|
.scale_viewport(scaling, viewport.output.size);
|
||||||
|
|
||||||
if fb.size != size {
|
if fb.size != size || (mipmap && fb.max_levels == 1) || (!mipmap && fb.max_levels != 1) {
|
||||||
fb.size = size;
|
fb.size = size;
|
||||||
|
if mipmap {
|
||||||
|
fb.max_levels = u32::MAX;
|
||||||
|
} else {
|
||||||
|
fb.max_levels = 1
|
||||||
|
}
|
||||||
Self::init(
|
Self::init(
|
||||||
fb,
|
fb,
|
||||||
size,
|
size,
|
||||||
|
|
|
@ -444,7 +444,12 @@ impl FilterChainVulkan {
|
||||||
|
|
||||||
/// Process a frame with the input image.
|
/// Process a frame with the input image.
|
||||||
///
|
///
|
||||||
/// When this frame returns, GL_FRAMEBUFFER is bound to 0.
|
/// * The input image must be in the `VK_SHADER_READ_ONLY_OPTIMAL`.
|
||||||
|
/// * The output image must be in `VK_COLOR_ATTACHMENT_OPTIMAL`.
|
||||||
|
///
|
||||||
|
/// librashader **will not** create a pipeline barrier for the final pass. The output image will
|
||||||
|
/// remain in `VK_COLOR_ATTACHMENT_OPTIMAL` after all shader passes. The caller must transition
|
||||||
|
/// the output image to the final layout.
|
||||||
pub fn frame(
|
pub fn frame(
|
||||||
&mut self,
|
&mut self,
|
||||||
count: usize,
|
count: usize,
|
||||||
|
@ -504,6 +509,8 @@ impl FilterChainVulkan {
|
||||||
&viewport.output.size,
|
&viewport.output.size,
|
||||||
&original,
|
&original,
|
||||||
&source,
|
&source,
|
||||||
|
// todo: need to check **next**
|
||||||
|
pass.config.mipmap_input
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,8 +533,12 @@ impl FilterChainVulkan {
|
||||||
|
|
||||||
pass.draw(cmd, index, &self.common, count as u32, 0,
|
pass.draw(cmd, index, &self.common, count as u32, 0,
|
||||||
viewport, &original, &source, &out)?;
|
viewport, &original, &source, &out)?;
|
||||||
// for second to last pass, we want to transition to copy instead.
|
|
||||||
out.output.end_pass(cmd);
|
if target.max_miplevels > 1 {
|
||||||
|
target.generate_mipmaps_and_end_pass(cmd);
|
||||||
|
} else {
|
||||||
|
out.output.end_pass(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
source = target.as_input(pass.config.filter, pass.config.wrap_mode)?;
|
source = target.as_input(pass.config.filter, pass.config.wrap_mode)?;
|
||||||
let prev_frame_output = self.common
|
let prev_frame_output = self.common
|
||||||
|
|
|
@ -2,7 +2,6 @@ use crate::{error, util};
|
||||||
use crate::filter_chain::Vulkan;
|
use crate::filter_chain::Vulkan;
|
||||||
use crate::texture::{VulkanImage};
|
use crate::texture::{VulkanImage};
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
use ash::vk::{ImageAspectFlags, ImageViewType};
|
|
||||||
use librashader_common::Size;
|
use librashader_common::Size;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -21,7 +20,7 @@ impl OutputFramebuffer {
|
||||||
.base_array_layer(0)
|
.base_array_layer(0)
|
||||||
.level_count(1)
|
.level_count(1)
|
||||||
.layer_count(1)
|
.layer_count(1)
|
||||||
.aspect_mask(ImageAspectFlags::COLOR)
|
.aspect_mask(vk::ImageAspectFlags::COLOR)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let swizzle_components = vk::ComponentMapping::builder()
|
let swizzle_components = vk::ComponentMapping::builder()
|
||||||
|
@ -32,7 +31,7 @@ impl OutputFramebuffer {
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let mut view_info = vk::ImageViewCreateInfo::builder()
|
let mut view_info = vk::ImageViewCreateInfo::builder()
|
||||||
.view_type(ImageViewType::TYPE_2D)
|
.view_type(vk::ImageViewType::TYPE_2D)
|
||||||
.format(image.format)
|
.format(image.format)
|
||||||
.image(image.image.clone())
|
.image(image.image.clone())
|
||||||
.subresource_range(image_subresource)
|
.subresource_range(image_subresource)
|
||||||
|
|
|
@ -3,10 +3,7 @@ use crate::filter_chain::Vulkan;
|
||||||
use crate::util::find_vulkan_memory_type;
|
use crate::util::find_vulkan_memory_type;
|
||||||
use crate::vulkan_primitives::VulkanImageMemory;
|
use crate::vulkan_primitives::VulkanImageMemory;
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
use ash::vk::{
|
|
||||||
ImageAspectFlags, ImageLayout, ImageTiling, ImageType, ImageUsageFlags, ImageViewType,
|
|
||||||
SampleCountFlags, SharingMode,
|
|
||||||
};
|
|
||||||
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
|
use librashader_common::{FilterMode, ImageFormat, Size, WrapMode};
|
||||||
use librashader_presets::Scale2D;
|
use librashader_presets::Scale2D;
|
||||||
use librashader_runtime::scaling::{MipmapSize, ViewportSize};
|
use librashader_runtime::scaling::{MipmapSize, ViewportSize};
|
||||||
|
@ -18,6 +15,7 @@ pub struct OwnedTexture {
|
||||||
pub image: VulkanImage,
|
pub image: VulkanImage,
|
||||||
pub memory: VulkanImageMemory,
|
pub memory: VulkanImageMemory,
|
||||||
pub max_miplevels: u32,
|
pub max_miplevels: u32,
|
||||||
|
pub levels: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OwnedTexture {
|
impl OwnedTexture {
|
||||||
|
@ -29,22 +27,22 @@ impl OwnedTexture {
|
||||||
max_miplevels: u32,
|
max_miplevels: u32,
|
||||||
) -> error::Result<OwnedTexture> {
|
) -> error::Result<OwnedTexture> {
|
||||||
let image_create_info = vk::ImageCreateInfo::builder()
|
let image_create_info = vk::ImageCreateInfo::builder()
|
||||||
.image_type(ImageType::TYPE_2D)
|
.image_type(vk::ImageType::TYPE_2D)
|
||||||
.format(format.into())
|
.format(format.into())
|
||||||
.extent(size.into())
|
.extent(size.into())
|
||||||
.mip_levels(std::cmp::min(max_miplevels, size.calculate_miplevels()))
|
.mip_levels(std::cmp::min(max_miplevels, size.calculate_miplevels()))
|
||||||
.array_layers(1)
|
.array_layers(1)
|
||||||
.samples(SampleCountFlags::TYPE_1)
|
.samples(vk::SampleCountFlags::TYPE_1)
|
||||||
.tiling(ImageTiling::OPTIMAL)
|
.tiling(vk::ImageTiling::OPTIMAL)
|
||||||
.flags(vk::ImageCreateFlags::MUTABLE_FORMAT)
|
.flags(vk::ImageCreateFlags::MUTABLE_FORMAT)
|
||||||
.usage(
|
.usage(
|
||||||
ImageUsageFlags::SAMPLED
|
vk::ImageUsageFlags::SAMPLED
|
||||||
| ImageUsageFlags::COLOR_ATTACHMENT
|
| vk::ImageUsageFlags::COLOR_ATTACHMENT
|
||||||
| ImageUsageFlags::TRANSFER_DST
|
| vk::ImageUsageFlags::TRANSFER_DST
|
||||||
| ImageUsageFlags::TRANSFER_SRC,
|
| vk::ImageUsageFlags::TRANSFER_SRC,
|
||||||
)
|
)
|
||||||
.sharing_mode(SharingMode::EXCLUSIVE)
|
.sharing_mode(vk::SharingMode::EXCLUSIVE)
|
||||||
.initial_layout(ImageLayout::UNDEFINED)
|
.initial_layout(vk::ImageLayout::UNDEFINED)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let image = unsafe { device.create_image(&image_create_info, None)? };
|
let image = unsafe { device.create_image(&image_create_info, None)? };
|
||||||
|
@ -68,7 +66,7 @@ impl OwnedTexture {
|
||||||
.base_array_layer(0)
|
.base_array_layer(0)
|
||||||
.level_count(image_create_info.mip_levels)
|
.level_count(image_create_info.mip_levels)
|
||||||
.layer_count(1)
|
.layer_count(1)
|
||||||
.aspect_mask(ImageAspectFlags::COLOR)
|
.aspect_mask(vk::ImageAspectFlags::COLOR)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let swizzle_components = vk::ComponentMapping::builder()
|
let swizzle_components = vk::ComponentMapping::builder()
|
||||||
|
@ -79,7 +77,7 @@ impl OwnedTexture {
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let mut view_info = vk::ImageViewCreateInfo::builder()
|
let mut view_info = vk::ImageViewCreateInfo::builder()
|
||||||
.view_type(ImageViewType::TYPE_2D)
|
.view_type(vk::ImageViewType::TYPE_2D)
|
||||||
.format(format.into())
|
.format(format.into())
|
||||||
.image(image.clone())
|
.image(image.clone())
|
||||||
.subresource_range(image_subresource)
|
.subresource_range(image_subresource)
|
||||||
|
@ -99,6 +97,7 @@ impl OwnedTexture {
|
||||||
},
|
},
|
||||||
memory,
|
memory,
|
||||||
max_miplevels,
|
max_miplevels,
|
||||||
|
levels: std::cmp::min(max_miplevels, size.calculate_miplevels())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,17 +117,21 @@ impl OwnedTexture {
|
||||||
viewport_size: &Size<u32>,
|
viewport_size: &Size<u32>,
|
||||||
_original: &InputTexture,
|
_original: &InputTexture,
|
||||||
source: &InputTexture,
|
source: &InputTexture,
|
||||||
|
mipmap: bool,
|
||||||
) -> error::Result<Size<u32>> {
|
) -> error::Result<Size<u32>> {
|
||||||
|
|
||||||
|
|
||||||
let size = source.image.size.scale_viewport(scaling, *viewport_size);
|
let size = source.image.size.scale_viewport(scaling, *viewport_size);
|
||||||
|
if self.image.size != size || (mipmap && self.max_miplevels == 1) || (!mipmap && self.max_miplevels != 1) {
|
||||||
|
let max_levels = if mipmap {
|
||||||
|
u32::MAX
|
||||||
|
} else {
|
||||||
|
1
|
||||||
|
};
|
||||||
|
|
||||||
if self.image.size != size {
|
|
||||||
let mut new = OwnedTexture::new_internal(self.device.clone(), self.mem_props, size, if format == ImageFormat::Unknown {
|
let mut new = OwnedTexture::new_internal(self.device.clone(), self.mem_props, size, if format == ImageFormat::Unknown {
|
||||||
ImageFormat::R8G8B8A8Unorm
|
ImageFormat::R8G8B8A8Unorm
|
||||||
} else {
|
} else {
|
||||||
format
|
format
|
||||||
}, self.max_miplevels)?;
|
}, max_levels)?;
|
||||||
|
|
||||||
let old = std::mem::replace(self, new);
|
let old = std::mem::replace(self, new);
|
||||||
drop(old)
|
drop(old)
|
||||||
|
@ -143,7 +146,7 @@ impl OwnedTexture {
|
||||||
.base_array_layer(0)
|
.base_array_layer(0)
|
||||||
.level_count(1)
|
.level_count(1)
|
||||||
.layer_count(1)
|
.layer_count(1)
|
||||||
.aspect_mask(ImageAspectFlags::COLOR)
|
.aspect_mask(vk::ImageAspectFlags::COLOR)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let swizzle_components = vk::ComponentMapping::builder()
|
let swizzle_components = vk::ComponentMapping::builder()
|
||||||
|
@ -154,7 +157,7 @@ impl OwnedTexture {
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let mut view_info = vk::ImageViewCreateInfo::builder()
|
let mut view_info = vk::ImageViewCreateInfo::builder()
|
||||||
.view_type(ImageViewType::TYPE_2D)
|
.view_type(vk::ImageViewType::TYPE_2D)
|
||||||
.format(self.image.format)
|
.format(self.image.format)
|
||||||
.image(self.image.image.clone())
|
.image(self.image.image.clone())
|
||||||
.subresource_range(image_subresource)
|
.subresource_range(image_subresource)
|
||||||
|
@ -174,6 +177,286 @@ impl OwnedTexture {
|
||||||
mip_filter: filter,
|
mip_filter: filter,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn generate_mipmaps_and_end_pass(&self, cmd: vk::CommandBuffer) {
|
||||||
|
let input_barrier = vk::ImageMemoryBarrier::builder()
|
||||||
|
.src_access_mask(vk::AccessFlags::COLOR_ATTACHMENT_WRITE)
|
||||||
|
.dst_access_mask(vk::AccessFlags::TRANSFER_READ)
|
||||||
|
.old_layout(vk::ImageLayout::COLOR_ATTACHMENT_OPTIMAL)
|
||||||
|
.new_layout(vk::ImageLayout::TRANSFER_SRC_OPTIMAL)
|
||||||
|
.src_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
|
||||||
|
.dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
|
||||||
|
.image(self.image.image)
|
||||||
|
.subresource_range(vk::ImageSubresourceRange {
|
||||||
|
aspect_mask: vk::ImageAspectFlags::COLOR,
|
||||||
|
base_mip_level: 0,
|
||||||
|
level_count: 1,
|
||||||
|
base_array_layer: 0,
|
||||||
|
layer_count: vk::REMAINING_ARRAY_LAYERS
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
let mipchain_barrier = vk::ImageMemoryBarrier::builder()
|
||||||
|
.src_access_mask(vk::AccessFlags::empty())
|
||||||
|
.dst_access_mask(vk::AccessFlags::TRANSFER_WRITE)
|
||||||
|
.old_layout(vk::ImageLayout::UNDEFINED)
|
||||||
|
.new_layout(vk::ImageLayout::TRANSFER_DST_OPTIMAL)
|
||||||
|
.src_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
|
||||||
|
.dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
|
||||||
|
.image(self.image.image)
|
||||||
|
.subresource_range(vk::ImageSubresourceRange {
|
||||||
|
aspect_mask: vk::ImageAspectFlags::COLOR,
|
||||||
|
base_mip_level: 1,
|
||||||
|
base_array_layer: 0,
|
||||||
|
level_count: vk::REMAINING_MIP_LEVELS,
|
||||||
|
layer_count: vk::REMAINING_ARRAY_LAYERS
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
self.device.cmd_pipeline_barrier(cmd,
|
||||||
|
vk::PipelineStageFlags::ALL_GRAPHICS,
|
||||||
|
vk::PipelineStageFlags::TRANSFER,
|
||||||
|
vk::DependencyFlags::empty(),
|
||||||
|
&[],
|
||||||
|
&[],
|
||||||
|
&[input_barrier, mipchain_barrier]
|
||||||
|
);
|
||||||
|
|
||||||
|
for level in 1..self.levels {
|
||||||
|
// need to transition from DST to SRC, one level at a time.
|
||||||
|
if level > 1 {
|
||||||
|
|
||||||
|
let next_barrier = vk::ImageMemoryBarrier::builder()
|
||||||
|
.src_access_mask(vk::AccessFlags::TRANSFER_WRITE)
|
||||||
|
.dst_access_mask(vk::AccessFlags::TRANSFER_READ)
|
||||||
|
.old_layout(vk::ImageLayout::TRANSFER_DST_OPTIMAL)
|
||||||
|
.new_layout(vk::ImageLayout::TRANSFER_SRC_OPTIMAL)
|
||||||
|
.src_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
|
||||||
|
.dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
|
||||||
|
.image(self.image.image)
|
||||||
|
.subresource_range(vk::ImageSubresourceRange {
|
||||||
|
aspect_mask: vk::ImageAspectFlags::COLOR,
|
||||||
|
base_mip_level: level - 1,
|
||||||
|
base_array_layer: 0,
|
||||||
|
level_count: 1,
|
||||||
|
layer_count: vk::REMAINING_ARRAY_LAYERS
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
|
||||||
|
self.device.cmd_pipeline_barrier(cmd,
|
||||||
|
vk::PipelineStageFlags::TRANSFER,
|
||||||
|
vk::PipelineStageFlags::TRANSFER,
|
||||||
|
vk::DependencyFlags::empty(),
|
||||||
|
&[],
|
||||||
|
&[],
|
||||||
|
&[next_barrier]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let source_size = self.image.size.scale_mipmap(level - 1);
|
||||||
|
let target_size = self.image.size.scale_mipmap(level);
|
||||||
|
|
||||||
|
let src_offsets = [
|
||||||
|
vk::Offset3D { x: 0, y: 0, z: 0 },
|
||||||
|
vk::Offset3D {
|
||||||
|
x: source_size.width as i32,
|
||||||
|
y: source_size.height as i32,
|
||||||
|
z: 1,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let dst_offsets = [
|
||||||
|
vk::Offset3D { x: 0, y: 0, z: 0 },
|
||||||
|
vk::Offset3D {
|
||||||
|
x: target_size.width as i32,
|
||||||
|
y: target_size.height as i32,
|
||||||
|
z: 1,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let src_subresource = vk::ImageSubresourceLayers::builder()
|
||||||
|
.aspect_mask(vk::ImageAspectFlags::COLOR)
|
||||||
|
.mip_level(level - 1)
|
||||||
|
.base_array_layer(0)
|
||||||
|
.layer_count(1)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let dst_subresource = vk::ImageSubresourceLayers::builder()
|
||||||
|
.aspect_mask(vk::ImageAspectFlags::COLOR)
|
||||||
|
.mip_level(level)
|
||||||
|
.base_array_layer(0)
|
||||||
|
.layer_count(1)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let image_blit = [vk::ImageBlit::builder()
|
||||||
|
.src_subresource(src_subresource)
|
||||||
|
.src_offsets(src_offsets)
|
||||||
|
.dst_subresource(dst_subresource)
|
||||||
|
.dst_offsets(dst_offsets)
|
||||||
|
.build()];
|
||||||
|
|
||||||
|
self.device.cmd_blit_image(
|
||||||
|
cmd,
|
||||||
|
self.image.image,
|
||||||
|
vk::ImageLayout::TRANSFER_SRC_OPTIMAL,
|
||||||
|
self.image.image,
|
||||||
|
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
|
||||||
|
&image_blit,
|
||||||
|
vk::Filter::LINEAR,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// move everything to SHADER_READ_ONLY_OPTIMAL
|
||||||
|
|
||||||
|
let input_barrier = vk::ImageMemoryBarrier::builder()
|
||||||
|
.src_access_mask(vk::AccessFlags::TRANSFER_READ)
|
||||||
|
.dst_access_mask(vk::AccessFlags::SHADER_READ)
|
||||||
|
.old_layout(vk::ImageLayout::TRANSFER_SRC_OPTIMAL)
|
||||||
|
.new_layout(vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL)
|
||||||
|
.src_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
|
||||||
|
.dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
|
||||||
|
.image(self.image.image)
|
||||||
|
.subresource_range(vk::ImageSubresourceRange {
|
||||||
|
aspect_mask: vk::ImageAspectFlags::COLOR,
|
||||||
|
base_mip_level: 0,
|
||||||
|
level_count: self.levels - 1,
|
||||||
|
base_array_layer: 0,
|
||||||
|
layer_count: vk::REMAINING_ARRAY_LAYERS
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
let mipchain_barrier = vk::ImageMemoryBarrier::builder()
|
||||||
|
.src_access_mask(vk::AccessFlags::TRANSFER_WRITE)
|
||||||
|
.dst_access_mask(vk::AccessFlags::SHADER_READ)
|
||||||
|
.old_layout(vk::ImageLayout::TRANSFER_DST_OPTIMAL)
|
||||||
|
.new_layout(vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL)
|
||||||
|
.src_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
|
||||||
|
.dst_queue_family_index(vk::QUEUE_FAMILY_IGNORED)
|
||||||
|
.image(self.image.image)
|
||||||
|
.subresource_range(vk::ImageSubresourceRange {
|
||||||
|
aspect_mask: vk::ImageAspectFlags::COLOR,
|
||||||
|
base_mip_level: self.levels - 1,
|
||||||
|
base_array_layer: 0,
|
||||||
|
level_count: 1,
|
||||||
|
layer_count: vk::REMAINING_ARRAY_LAYERS
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// next past waits for ALL_GRAPHICS, use dependency chain and FRAGMENT_SHADER dst stage
|
||||||
|
// to ensure that next pass doesn't start until mipchain is complete.
|
||||||
|
self.device.cmd_pipeline_barrier(cmd,
|
||||||
|
vk::PipelineStageFlags::TRANSFER,
|
||||||
|
vk::PipelineStageFlags::FRAGMENT_SHADER,
|
||||||
|
vk::DependencyFlags::empty(),
|
||||||
|
&[],
|
||||||
|
&[],
|
||||||
|
&[input_barrier, mipchain_barrier]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// SAFETY: self must fit the source image
|
||||||
|
pub unsafe fn copy_from(&self, cmd: vk::CommandBuffer, source: VulkanImage, source_layout: vk::ImageLayout) {
|
||||||
|
let region = vk::ImageCopy::builder()
|
||||||
|
.src_subresource(vk::ImageSubresourceLayers::builder()
|
||||||
|
.aspect_mask(vk::ImageAspectFlags::COLOR)
|
||||||
|
.mip_level(0)
|
||||||
|
.base_array_layer(0)
|
||||||
|
.layer_count(1)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.dst_subresource(vk::ImageSubresourceLayers::builder()
|
||||||
|
.aspect_mask(vk::ImageAspectFlags::COLOR)
|
||||||
|
.mip_level(0)
|
||||||
|
.base_array_layer(0)
|
||||||
|
.layer_count(1)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.src_offset(Default::default())
|
||||||
|
.dst_offset(Default::default())
|
||||||
|
.extent(source.size.into())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
util::vulkan_image_layout_transition_levels(&self.device,
|
||||||
|
cmd,
|
||||||
|
self.image.image,
|
||||||
|
vk::REMAINING_MIP_LEVELS,
|
||||||
|
vk::ImageLayout::UNDEFINED,
|
||||||
|
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
|
||||||
|
vk::AccessFlags::empty(),
|
||||||
|
vk::AccessFlags::TRANSFER_WRITE,
|
||||||
|
vk::PipelineStageFlags::FRAGMENT_SHADER,
|
||||||
|
vk::PipelineStageFlags::TRANSFER,
|
||||||
|
vk::QUEUE_FAMILY_IGNORED, vk::QUEUE_FAMILY_IGNORED
|
||||||
|
);
|
||||||
|
|
||||||
|
self.device.cmd_copy_image(cmd, source.image, source_layout, self.image.image, vk::ImageLayout::TRANSFER_DST_OPTIMAL, &[region]);
|
||||||
|
util::vulkan_image_layout_transition_levels(&self.device,
|
||||||
|
cmd,
|
||||||
|
self.image.image,
|
||||||
|
vk::REMAINING_MIP_LEVELS,
|
||||||
|
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
|
||||||
|
vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
|
||||||
|
vk::AccessFlags::TRANSFER_WRITE,
|
||||||
|
vk::AccessFlags::SHADER_READ,
|
||||||
|
vk::PipelineStageFlags::TRANSFER,
|
||||||
|
vk::PipelineStageFlags::FRAGMENT_SHADER,
|
||||||
|
vk::QUEUE_FAMILY_IGNORED,
|
||||||
|
vk::QUEUE_FAMILY_IGNORED
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear(&self, cmd: vk::CommandBuffer) {
|
||||||
|
unsafe {
|
||||||
|
util::vulkan_image_layout_transition_levels(&self.device,
|
||||||
|
cmd,
|
||||||
|
self.image.image,
|
||||||
|
vk::REMAINING_MIP_LEVELS,
|
||||||
|
vk::ImageLayout::UNDEFINED,
|
||||||
|
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
|
||||||
|
vk::AccessFlags::empty(),
|
||||||
|
vk::AccessFlags::TRANSFER_WRITE,
|
||||||
|
vk::PipelineStageFlags::TOP_OF_PIPE,
|
||||||
|
vk::PipelineStageFlags::TRANSFER,
|
||||||
|
vk::QUEUE_FAMILY_IGNORED,
|
||||||
|
vk::QUEUE_FAMILY_IGNORED
|
||||||
|
);
|
||||||
|
self.device.cmd_clear_color_image(cmd,
|
||||||
|
self.image.image,
|
||||||
|
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
|
||||||
|
&vk::ClearColorValue {
|
||||||
|
float32: [0.0, 0.0, 0.0, 0.0]
|
||||||
|
},
|
||||||
|
&[vk::ImageSubresourceRange::builder()
|
||||||
|
.aspect_mask(vk::ImageAspectFlags::COLOR)
|
||||||
|
.base_mip_level(0)
|
||||||
|
.level_count(1)
|
||||||
|
.base_array_layer(0)
|
||||||
|
.layer_count(1)
|
||||||
|
.build()]
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
util::vulkan_image_layout_transition_levels(&self.device,
|
||||||
|
cmd,
|
||||||
|
self.image.image,
|
||||||
|
vk::REMAINING_MIP_LEVELS,
|
||||||
|
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
|
||||||
|
vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
|
||||||
|
vk::AccessFlags::TRANSFER_WRITE,
|
||||||
|
vk::AccessFlags::SHADER_READ,
|
||||||
|
vk::PipelineStageFlags::TRANSFER,
|
||||||
|
vk::PipelineStageFlags::FRAGMENT_SHADER,
|
||||||
|
vk::QUEUE_FAMILY_IGNORED,
|
||||||
|
vk::QUEUE_FAMILY_IGNORED
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for OwnedTexture {
|
impl Drop for OwnedTexture {
|
||||||
|
|
Loading…
Add table
Reference in a new issue