Sampler improvements (#1787)

* Sampler improvements

* Check Filter::Cubic for blits as well

* Small doc fix

* Better checks for blits

* Doc fix

* can_be_sampled > can_sample
This commit is contained in:
Rua 2022-01-11 04:32:53 +01:00 committed by GitHub
parent 6c111df9a7
commit 4c7cdb44fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 994 additions and 838 deletions

View File

@ -34,7 +34,7 @@ use vulkano::{
GraphicsPipeline, Pipeline, PipelineBindPoint,
},
render_pass::{Framebuffer, RenderPass, Subpass},
sampler::{Filter, MipmapMode, Sampler, SamplerAddressMode},
sampler::{Filter, Sampler, SamplerAddressMode},
swapchain::{AcquireError, Swapchain, SwapchainCreationError},
sync::{now, FlushError, GpuFuture, PipelineStages, Semaphore},
Version,
@ -493,20 +493,11 @@ fn vk_setup(
)
.unwrap();
let sampler = Sampler::new(
device.clone(),
Filter::Linear,
Filter::Linear,
MipmapMode::Nearest,
SamplerAddressMode::Repeat,
SamplerAddressMode::Repeat,
SamplerAddressMode::Repeat,
0.0,
1.0,
0.0,
0.0,
)
.unwrap();
let sampler = Sampler::start(device.clone())
.filter(Filter::Linear)
.address_mode(SamplerAddressMode::Repeat)
.build()
.unwrap();
let subpass = Subpass::from(render_pass.clone(), 0).unwrap();

View File

@ -26,7 +26,7 @@ use vulkano::pipeline::graphics::vertex_input::BuffersDefinition;
use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
use vulkano::render_pass::{Framebuffer, RenderPass, Subpass};
use vulkano::sampler::{Filter, MipmapMode, Sampler, SamplerAddressMode};
use vulkano::sampler::{Filter, Sampler, SamplerAddressMode};
use vulkano::swapchain::{self, AcquireError, Swapchain, SwapchainCreationError};
use vulkano::sync::{self, FlushError, GpuFuture};
use vulkano::Version;
@ -243,20 +243,11 @@ fn main() {
)
};
let sampler = Sampler::new(
device.clone(),
Filter::Linear,
Filter::Linear,
MipmapMode::Nearest,
SamplerAddressMode::Repeat,
SamplerAddressMode::Repeat,
SamplerAddressMode::Repeat,
0.0,
1.0,
0.0,
0.0,
)
.unwrap();
let sampler = Sampler::start(device.clone())
.filter(Filter::Linear)
.address_mode(SamplerAddressMode::Repeat)
.build()
.unwrap();
let subpass = Subpass::from(render_pass.clone(), 0).unwrap();
let pipeline = GraphicsPipeline::start()

View File

@ -27,7 +27,7 @@ use vulkano::pipeline::graphics::vertex_input::BuffersDefinition;
use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
use vulkano::render_pass::{Framebuffer, RenderPass, Subpass};
use vulkano::sampler::{Filter, MipmapMode, Sampler, SamplerAddressMode};
use vulkano::sampler::{Filter, Sampler, SamplerAddressMode};
use vulkano::swapchain::{self, AcquireError, Swapchain, SwapchainCreationError};
use vulkano::sync::{self, FlushError, GpuFuture};
use vulkano::Version;
@ -177,20 +177,11 @@ fn main() {
(ImageView::new(image).unwrap(), future)
};
let sampler = Sampler::new(
device.clone(),
Filter::Linear,
Filter::Linear,
MipmapMode::Nearest,
SamplerAddressMode::Repeat,
SamplerAddressMode::Repeat,
SamplerAddressMode::Repeat,
0.0,
1.0,
0.0,
0.0,
)
.unwrap();
let sampler = Sampler::start(device.clone())
.filter(Filter::Linear)
.address_mode(SamplerAddressMode::Repeat)
.build()
.unwrap();
let subpass = Subpass::from(render_pass.clone(), 0).unwrap();
let pipeline = GraphicsPipeline::start()

View File

@ -36,7 +36,7 @@ use vulkano::pipeline::graphics::vertex_input::BuffersDefinition;
use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
use vulkano::render_pass::{Framebuffer, RenderPass, Subpass};
use vulkano::sampler::{Filter, MipmapMode, Sampler, SamplerAddressMode};
use vulkano::sampler::{Filter, Sampler, SamplerAddressMode};
use vulkano::swapchain::{self, AcquireError, Swapchain, SwapchainCreationError};
use vulkano::sync::{self, FlushError, GpuFuture};
use vulkano::Version;
@ -183,20 +183,11 @@ fn main() {
(ImageView::new(image).unwrap(), future)
};
let sampler = Sampler::new(
device.clone(),
Filter::Linear,
Filter::Linear,
MipmapMode::Nearest,
SamplerAddressMode::Repeat,
SamplerAddressMode::Repeat,
SamplerAddressMode::Repeat,
0.0,
1.0,
0.0,
0.0,
)
.unwrap();
let sampler = Sampler::start(device.clone())
.filter(Filter::Linear)
.address_mode(SamplerAddressMode::Repeat)
.build()
.unwrap();
let subpass = Subpass::from(render_pass.clone(), 0).unwrap();
let pipeline = GraphicsPipeline::start()

View File

@ -20,7 +20,7 @@ use vulkano::pipeline::graphics::vertex_input::BuffersDefinition;
use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
use vulkano::render_pass::Subpass;
use vulkano::sampler::{Filter, MipmapMode, Sampler, SamplerAddressMode};
use vulkano::sampler::{Filter, Sampler, SamplerAddressMode, SamplerMipmapMode};
/// Vertex for textured quads
#[repr(C)]
@ -112,20 +112,13 @@ impl PixelsDrawPipeline {
.descriptor_set_layouts()
.get(0)
.unwrap();
let sampler = Sampler::new(
self.gfx_queue.device().clone(),
Filter::Linear,
Filter::Linear,
MipmapMode::Linear,
SamplerAddressMode::Repeat,
SamplerAddressMode::Repeat,
SamplerAddressMode::Repeat,
0.0,
1.0,
0.0,
0.0,
)
.unwrap();
let sampler = Sampler::start(self.gfx_queue.device().clone())
.filter(Filter::Linear)
.address_mode(SamplerAddressMode::Repeat)
.mipmap_mode(SamplerMipmapMode::Linear)
.build()
.unwrap();
PersistentDescriptorSet::new(
layout.clone(),
[WriteDescriptorSet::image_view_sampler(

View File

@ -27,7 +27,7 @@ use vulkano::pipeline::graphics::vertex_input::BuffersDefinition;
use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
use vulkano::render_pass::{Framebuffer, RenderPass, Subpass};
use vulkano::sampler::{Filter, MipmapMode, Sampler, SamplerAddressMode};
use vulkano::sampler::{Filter, Sampler, SamplerAddressMode};
use vulkano::swapchain::{self, AcquireError, Swapchain, SwapchainCreationError};
use vulkano::sync::{self, FlushError, GpuFuture};
use vulkano::Version;
@ -175,20 +175,11 @@ fn main() {
(ImageView::new(image).unwrap(), future)
};
let sampler = Sampler::new(
device.clone(),
Filter::Linear,
Filter::Linear,
MipmapMode::Nearest,
SamplerAddressMode::Repeat,
SamplerAddressMode::Repeat,
SamplerAddressMode::Repeat,
0.0,
1.0,
0.0,
0.0,
)
.unwrap();
let sampler = Sampler::start(device.clone())
.filter(Filter::Linear)
.address_mode(SamplerAddressMode::Repeat)
.build()
.unwrap();
let subpass = Subpass::from(render_pass.clone(), 0).unwrap();
let pipeline = GraphicsPipeline::start()

View File

@ -30,7 +30,7 @@ use vulkano::pipeline::graphics::viewport::{Viewport, ViewportState};
use vulkano::pipeline::layout::PipelineLayout;
use vulkano::pipeline::{GraphicsPipeline, Pipeline, PipelineBindPoint};
use vulkano::render_pass::{Framebuffer, RenderPass, Subpass};
use vulkano::sampler::{Filter, MipmapMode, Sampler, SamplerAddressMode};
use vulkano::sampler::{Filter, Sampler, SamplerAddressMode};
use vulkano::swapchain::{self, AcquireError, Swapchain, SwapchainCreationError};
use vulkano::sync::{self, FlushError, GpuFuture};
use vulkano::Version;
@ -266,20 +266,11 @@ fn main() {
ImageView::new(image).unwrap()
};
let sampler = Sampler::new(
device.clone(),
Filter::Linear,
Filter::Linear,
MipmapMode::Nearest,
SamplerAddressMode::Repeat,
SamplerAddressMode::Repeat,
SamplerAddressMode::Repeat,
0.0,
1.0,
0.0,
0.0,
)
.unwrap();
let sampler = Sampler::start(device.clone())
.filter(Filter::Linear)
.address_mode(SamplerAddressMode::Repeat)
.build()
.unwrap();
let pipeline_layout = {
let mut descriptor_set_descs: Vec<_> = DescriptorSetDesc::from_requirements(

View File

@ -687,7 +687,7 @@ mod tests {
set_layout.clone(),
[WriteDescriptorSet::sampler(
0,
Sampler::simple_repeat_linear(device.clone()),
Sampler::simple_repeat_linear(device.clone()).unwrap(),
)],
)
.unwrap();
@ -740,7 +740,7 @@ mod tests {
set_layout.clone(),
[WriteDescriptorSet::sampler(
0,
Sampler::simple_repeat_linear(device.clone()),
Sampler::simple_repeat_linear(device.clone()).unwrap(),
)],
)
.unwrap();

View File

@ -265,12 +265,54 @@ where
}
}
match filter {
Filter::Nearest => (),
Filter::Linear => {
if !source_inner
.image
.format_features()
.sampled_image_filter_linear
{
return Err(CheckBlitImageError::FilterFormatNotSupported);
}
}
Filter::Cubic => {
if !device.enabled_extensions().ext_filter_cubic {
return Err(CheckBlitImageError::ExtensionNotEnabled {
extension: "ext_filter_cubic",
reason: "the specified filter was Cubic",
});
}
if !source_inner
.image
.format_features()
.img_sampled_image_filter_cubic
{
return Err(CheckBlitImageError::FilterFormatNotSupported);
}
if !matches!(source.dimensions(), ImageDimensions::Dim2d { .. }) {
return Err(CheckBlitImageError::FilterDimensionalityNotSupported);
}
}
}
Ok(())
}
/// Error that can happen from `check_clear_color_image`.
#[derive(Debug, Copy, Clone)]
pub enum CheckBlitImageError {
ExtensionNotEnabled {
extension: &'static str,
reason: &'static str,
},
/// The chosen filter type does not support the dimensionality of the source image.
FilterDimensionalityNotSupported,
/// The chosen filter type does not support the format of the source image.
FilterFormatNotSupported,
/// The source is missing the transfer source usage.
MissingTransferSourceUsage,
/// The destination is missing the transfer destination usage.
@ -305,50 +347,71 @@ impl error::Error for CheckBlitImageError {}
impl fmt::Display for CheckBlitImageError {
#[inline]
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(
fmt,
"{}",
match *self {
CheckBlitImageError::MissingTransferSourceUsage => {
"the source is missing the transfer source usage"
}
CheckBlitImageError::MissingTransferDestinationUsage => {
"the destination is missing the transfer destination usage"
}
CheckBlitImageError::SourceFormatNotSupported => {
"the format of the source image doesn't support blit operations"
}
CheckBlitImageError::DestinationFormatNotSupported => {
"the format of the destination image doesn't support blit operations"
}
CheckBlitImageError::DepthStencilNearestMandatory => {
"you must use the nearest filter when blitting depth/stencil images"
}
CheckBlitImageError::DepthStencilFormatMismatch => {
"the format of the source and destination must be equal when blitting \
depth/stencil images"
}
CheckBlitImageError::IncompatibleFormatTypes { .. } => {
"the types of the source format and the destination format aren't compatible"
}
CheckBlitImageError::UnexpectedMultisampled => {
"blitting between multisampled images is forbidden"
}
CheckBlitImageError::SourceCoordinatesOutOfRange => {
"the offsets, array layers and/or mipmap levels are out of range in the source \
image"
}
CheckBlitImageError::DestinationCoordinatesOutOfRange => {
"the offsets, array layers and/or mipmap levels are out of range in the \
destination image"
}
CheckBlitImageError::IncompatibleRangeForImageType => {
"the top-left and/or bottom-right coordinates are incompatible with the image type"
}
CheckBlitImageError::OverlappingRegions => {
"the source and destination regions are overlapping"
}
match *self {
Self::ExtensionNotEnabled { extension, reason } => write!(
fmt,
"the extension {} must be enabled: {}",
extension, reason
),
Self::FilterDimensionalityNotSupported => write!(
fmt,
"the chosen filter type does not support the dimensionality of the source image"
),
Self::FilterFormatNotSupported => write!(
fmt,
"the chosen filter type does not support the format of the source image"
),
Self::MissingTransferSourceUsage => {
write!(fmt, "the source is missing the transfer source usage")
}
)
Self::MissingTransferDestinationUsage => {
write!(
fmt,
"the destination is missing the transfer destination usage"
)
}
Self::SourceFormatNotSupported => {
write!(
fmt,
"the format of the source image doesn't support blit operations"
)
}
Self::DestinationFormatNotSupported => {
write!(
fmt,
"the format of the destination image doesn't support blit operations"
)
}
Self::DepthStencilNearestMandatory => {
write!(
fmt,
"you must use the nearest filter when blitting depth/stencil images"
)
}
Self::DepthStencilFormatMismatch => {
write!(fmt, "the format of the source and destination must be equal when blitting depth/stencil images")
}
Self::IncompatibleFormatTypes { .. } => {
write!(
fmt,
"the types of the source format and the destination format aren't compatible"
)
}
Self::UnexpectedMultisampled => {
write!(fmt, "blitting between multisampled images is forbidden")
}
Self::SourceCoordinatesOutOfRange => {
write!(fmt, "the offsets, array layers and/or mipmap levels are out of range in the source image")
}
Self::DestinationCoordinatesOutOfRange => {
write!(fmt, "the offsets, array layers and/or mipmap levels are out of range in the destination image")
}
Self::IncompatibleRangeForImageType => {
write!(fmt, "the top-left and/or bottom-right coordinates are incompatible with the image type")
}
Self::OverlappingRegions => {
write!(fmt, "the source and destination regions are overlapping")
}
}
}
}

View File

@ -569,7 +569,7 @@ pub(crate) fn check_descriptor_write<'a>(
});
}
if !image_view.can_be_sampled(sampler) {
if !sampler.can_sample(image_view.as_ref()) {
return Err(DescriptorSetUpdateError::ImageViewIncompatibleSampler {
binding: write.binding(),
index: descriptor_range_start + index as u32,
@ -681,7 +681,7 @@ pub(crate) fn check_descriptor_write<'a>(
});
}
if !image_view.can_be_sampled(&sampler) {
if !sampler.can_sample(image_view.as_ref()) {
return Err(DescriptorSetUpdateError::ImageViewIncompatibleSampler {
binding: write.binding(),
index: descriptor_range_start + index as u32,

View File

@ -21,7 +21,6 @@ use crate::image::sys::UnsafeImage;
use crate::image::ImageAccess;
use crate::image::ImageDimensions;
use crate::memory::DeviceMemoryAllocError;
use crate::sampler::Sampler;
use crate::OomError;
use crate::VulkanObject;
use std::error;
@ -615,15 +614,6 @@ pub unsafe trait ImageViewAbstract: DeviceOwned + Send + Sync {
/// Returns the [`ImageViewType`] of this image view.
fn ty(&self) -> ImageViewType;
/// Returns true if the given sampler can be used with this image view.
///
/// This method should check whether the sampler's configuration can be used with the format
/// of the view.
// TODO: return a Result and propagate it when binding to a descriptor set
fn can_be_sampled(&self, _sampler: &Sampler) -> bool {
true /* FIXME */
}
}
unsafe impl<I> ImageViewAbstract for ImageView<I>

File diff suppressed because it is too large Load Diff