steamvr poc works

This commit is contained in:
galister
2024-01-23 16:43:17 +01:00
parent 6cfbc6ffcd
commit 51160f97fe
12 changed files with 817 additions and 376 deletions

View File

@@ -1,22 +1,26 @@
use std::{error::Error, io::Cursor, slice::Iter, sync::Arc};
use std::{
error::Error,
io::Cursor,
os::fd::{FromRawFd, IntoRawFd},
slice::Iter,
sync::Arc,
};
use ash::vk::SubmitInfo;
use smallvec::smallvec;
use smallvec::{smallvec, SmallVec};
use vulkano::{
buffer::{
allocator::{SubbufferAllocator, SubbufferAllocatorCreateInfo},
Buffer, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer,
},
command_buffer::{
allocator::{
CommandBufferAllocator, CommandBufferBuilderAlloc, StandardCommandBufferAllocator,
},
allocator::{StandardCommandBufferAllocator, StandardCommandBufferAllocatorCreateInfo},
sys::{CommandBufferBeginInfo, UnsafeCommandBufferBuilder},
AutoCommandBufferBuilder, CommandBufferExecFuture, CommandBufferInheritanceInfo,
CommandBufferInheritanceRenderPassType, CommandBufferInheritanceRenderingInfo,
CommandBufferLevel, CommandBufferUsage, PrimaryAutoCommandBuffer,
PrimaryCommandBufferAbstract, RenderingAttachmentInfo, RenderingInfo,
SecondaryAutoCommandBuffer, SubpassContents,
CommandBufferInheritanceRenderPassInfo, CommandBufferInheritanceRenderPassType,
CommandBufferLevel, CommandBufferUsage, CopyBufferToImageInfo, PrimaryAutoCommandBuffer,
PrimaryCommandBufferAbstract, RenderPassBeginInfo, SecondaryAutoCommandBuffer,
SubpassBeginInfo, SubpassContents, SubpassEndInfo,
},
descriptor_set::{
allocator::StandardDescriptorSetAllocator, PersistentDescriptorSet, WriteDescriptorSet,
@@ -27,33 +31,47 @@ use vulkano::{
},
format::Format,
image::{
sys::Image, AttachmentImage, ImageCreateFlags, ImageDimensions, ImageError, ImageLayout,
ImageUsage, ImageViewAbstract, ImmutableImage, MipmapsCount, StorageImage, SubresourceData,
SwapchainImage,
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
sys::RawImage,
view::ImageView,
Image, ImageCreateInfo, ImageLayout, ImageTiling, ImageType, ImageUsage, SampleCount,
SubresourceLayout,
},
instance::{Instance, InstanceCreateFlags, InstanceCreateInfo, InstanceExtensions},
memory::{
allocator::{
AllocationCreateInfo, MemoryAllocator, MemoryTypeFilter, StandardMemoryAllocator,
},
DedicatedAllocation, DeviceMemory, ExternalMemoryHandleType, ExternalMemoryHandleTypes,
MemoryAllocateInfo, MemoryImportInfo, ResourceMemory,
},
instance::{Instance, InstanceCreateInfo, InstanceExtensions},
memory::allocator::{AllocationCreateInfo, MemoryUsage, StandardMemoryAllocator},
pipeline::{
graphics::{
color_blend::{AttachmentBlend, ColorBlendState},
color_blend::{AttachmentBlend, ColorBlendAttachmentState, ColorBlendState},
input_assembly::InputAssemblyState,
render_pass::PipelineRenderingCreateInfo,
vertex_input::Vertex,
multisample::MultisampleState,
rasterization::RasterizationState,
vertex_input::{Vertex, VertexDefinition},
viewport::{Viewport, ViewportState},
GraphicsPipelineCreateInfo,
},
GraphicsPipeline, Pipeline, PipelineBindPoint,
layout::PipelineDescriptorSetLayoutCreateInfo,
DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout,
PipelineShaderStageCreateInfo,
},
render_pass::{
AttachmentDescription, AttachmentLoadOp, AttachmentReference, AttachmentStoreOp,
Framebuffer, FramebufferCreateInfo, RenderPass, RenderPassCreateInfo, Subpass,
SubpassDescription,
},
render_pass::{LoadOp, StoreOp},
sampler::{Filter, Sampler, SamplerAddressMode, SamplerCreateInfo},
shader::ShaderModule,
swapchain::{CompositeAlpha, Surface, Swapchain, SwapchainCreateInfo},
sync::{
fence::Fence, future::NowFuture, AccessFlags, DependencyInfo, GpuFuture,
ImageMemoryBarrier, PipelineStages,
},
Version, VulkanLibrary, VulkanObject,
DeviceSize, VulkanLibrary, VulkanObject,
};
use vulkano_win::VkSurfaceBuild;
use winit::{
event_loop::EventLoop,
window::{Window, WindowBuilder},
@@ -98,8 +116,11 @@ impl WlxGraphics {
#[cfg(not(debug_assertions))]
let layers = vec![];
// TODO headless
let event_loop = EventLoop::new();
let library_extensions = Surface::required_extensions(&event_loop);
let library = VulkanLibrary::new().unwrap();
let library_extensions = vulkano_win::required_extensions(&library);
let required_extensions = library_extensions.union(&vk_instance_extensions);
log::debug!("Instance exts for app: {:?}", &required_extensions);
@@ -108,9 +129,9 @@ impl WlxGraphics {
let instance = Instance::new(
library,
InstanceCreateInfo {
flags: InstanceCreateFlags::ENUMERATE_PORTABILITY,
enabled_extensions: required_extensions,
enabled_layers: layers,
enumerate_portability: true,
..Default::default()
},
)
@@ -128,17 +149,15 @@ impl WlxGraphics {
log::debug!("Device exts for app: {:?}", &device_extensions);
// TODO headless
let event_loop = EventLoop::new();
let surface = WindowBuilder::new()
.build_vk_surface(&event_loop, instance.clone())
.unwrap();
let window = Arc::new(WindowBuilder::new().build(&event_loop).unwrap());
let surface = Surface::from_window(instance.clone(), window.clone()).unwrap();
let (physical_device, my_extensions, queue_family_index) = instance
.enumerate_physical_devices()
.unwrap()
.filter(|p| {
p.api_version() >= Version::V1_3 || p.supported_extensions().khr_dynamic_rendering
})
//.filter(|p| {
// p.api_version() >= Version::V1_3 || p.supported_extensions().khr_dynamic_rendering
//})
.filter_map(|p| {
let runtime_extensions = vk_device_extensions_fn(&p);
log::debug!(
@@ -178,9 +197,9 @@ impl WlxGraphics {
physical_device.properties().device_name,
);
if physical_device.api_version() < Version::V1_3 {
device_extensions.khr_dynamic_rendering = true;
}
//if physical_device.api_version() < Version::V1_3 {
// device_extensions.khr_dynamic_rendering = true;
//}
let (device, mut queues) = Device::new(
physical_device,
@@ -203,11 +222,16 @@ impl WlxGraphics {
let memory_allocator = Arc::new(StandardMemoryAllocator::new_default(device.clone()));
let command_buffer_allocator = Arc::new(StandardCommandBufferAllocator::new(
device.clone(),
StandardCommandBufferAllocatorCreateInfo {
secondary_buffer_count: 32,
..Default::default()
},
));
let descriptor_set_allocator = Arc::new(StandardDescriptorSetAllocator::new(
device.clone(),
Default::default(),
));
let descriptor_set_allocator =
Arc::new(StandardDescriptorSetAllocator::new(device.clone()));
let vertices = [
Vert2Uv {
@@ -228,13 +252,14 @@ impl WlxGraphics {
},
];
let quad_verts = Buffer::from_iter(
&memory_allocator,
memory_allocator.clone(),
BufferCreateInfo {
usage: BufferUsage::VERTEX_BUFFER,
..Default::default()
},
AllocationCreateInfo {
usage: MemoryUsage::Upload,
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
..Default::default()
},
vertices.into_iter(),
@@ -242,13 +267,14 @@ impl WlxGraphics {
.unwrap();
let quad_indices = Buffer::from_iter(
&memory_allocator,
memory_allocator.clone(),
BufferCreateInfo {
usage: BufferUsage::INDEX_BUFFER,
..Default::default()
},
AllocationCreateInfo {
usage: MemoryUsage::Upload,
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
..Default::default()
},
INDICES.iter().cloned(),
@@ -271,10 +297,7 @@ impl WlxGraphics {
}
#[allow(dead_code)]
pub fn create_swapchain(
&self,
format: Option<Format>,
) -> (Arc<Swapchain>, Vec<Arc<SwapchainImage>>) {
pub fn create_swapchain(&self, format: Option<Format>) -> (Arc<Swapchain>, Vec<Arc<Image>>) {
let (min_image_count, composite_alpha, image_format) = if let Some(format) = format {
(1, CompositeAlpha::Opaque, format)
} else {
@@ -314,7 +337,7 @@ impl WlxGraphics {
self.surface.clone(),
SwapchainCreateInfo {
min_image_count,
image_format: Some(image_format),
image_format,
image_extent: window.inner_size().into(),
image_usage: ImageUsage::COLOR_ATTACHMENT,
composite_alpha,
@@ -370,13 +393,14 @@ impl WlxGraphics {
T: BufferContents + Clone,
{
Buffer::from_iter(
&self.memory_allocator,
self.memory_allocator.clone(),
BufferCreateInfo {
usage,
..Default::default()
},
AllocationCreateInfo {
usage: MemoryUsage::Upload,
memory_type_filter: MemoryTypeFilter::PREFER_HOST
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
..Default::default()
},
contents.cloned(),
@@ -384,12 +408,8 @@ impl WlxGraphics {
.unwrap()
}
pub fn dmabuf_texture(&self, frame: DmabufFrame) -> Result<Arc<StorageImage>, ImageError> {
let dimensions = ImageDimensions::Dim2d {
width: frame.format.width,
height: frame.format.height,
array_layers: 1,
};
pub fn dmabuf_texture(&self, frame: DmabufFrame) -> Option<Arc<Image>> {
let extent = [frame.format.width, frame.format.height, 1];
let format = match frame.format.fourcc {
DRM_FORMAT_ABGR8888 => Format::R8G8B8A8_UNORM,
@@ -399,60 +419,145 @@ impl WlxGraphics {
_ => panic!("Unsupported dmabuf format {:x}", frame.format.fourcc),
};
let planes = frame
.planes
.iter()
.take(frame.num_planes)
.filter_map(|plane| {
let Some(fd) = plane.fd else {
return None;
};
Some(SubresourceData {
fd,
let layouts: Vec<SubresourceLayout> = (0..frame.num_planes)
.into_iter()
.map(|i| {
let plane = &frame.planes[i];
SubresourceLayout {
offset: plane.offset as _,
size: 0,
row_pitch: plane.stride as _,
})
array_pitch: None,
depth_pitch: None,
}
})
.collect();
StorageImage::new_from_dma_buf_fd(
&self.memory_allocator,
self.device.clone(),
dimensions,
format,
ImageUsage::SAMPLED | ImageUsage::TRANSFER_SRC,
ImageCreateFlags::empty(),
[self.queue.queue_family_index()],
planes,
frame.format.modifier,
)
}
let external_memory_handle_types = ExternalMemoryHandleTypes::DMA_BUF;
pub fn render_texture(&self, width: u32, height: u32, format: Format) -> Arc<AttachmentImage> {
let tex = AttachmentImage::with_usage(
&self.memory_allocator,
[width, height],
format,
ImageUsage::SAMPLED | ImageUsage::TRANSFER_SRC | ImageUsage::COLOR_ATTACHMENT,
let image = RawImage::new(
self.device.clone(),
ImageCreateInfo {
image_type: ImageType::Dim2d,
format,
extent,
usage: ImageUsage::SAMPLED | ImageUsage::TRANSFER_SRC,
external_memory_handle_types,
tiling: ImageTiling::DrmFormatModifier,
drm_format_modifiers: vec![frame.format.modifier],
drm_format_modifier_plane_layouts: layouts,
..Default::default()
},
)
.unwrap();
tex
let requirements = image.memory_requirements()[0];
let memory_type_index = self
.memory_allocator
.find_memory_type_index(
requirements.memory_type_bits,
MemoryTypeFilter::PREFER_DEVICE,
)
.unwrap();
debug_assert!(self.device.enabled_extensions().khr_external_memory_fd);
debug_assert!(self.device.enabled_extensions().khr_external_memory);
debug_assert!(self.device.enabled_extensions().ext_external_memory_dma_buf);
let memory = unsafe {
if frame.num_planes != 1 {
log::error!("Unsupported number of DMA-buf planes: {}", frame.num_planes);
return None;
}
let Some(fd) = frame.planes[0].fd else {
log::error!("DMA-buf plane has no FD");
return None;
};
let file = std::fs::File::from_raw_fd(fd);
let new_file = file.try_clone().unwrap();
file.into_raw_fd();
DeviceMemory::import(
self.device.clone(),
MemoryAllocateInfo {
allocation_size: requirements.layout.size(),
memory_type_index,
dedicated_allocation: Some(DedicatedAllocation::Image(&image)),
..Default::default()
},
MemoryImportInfo::Fd {
file: new_file,
handle_type: ExternalMemoryHandleType::DmaBuf,
},
)
.unwrap()
};
let allocations: SmallVec<[ResourceMemory; 1]> =
smallvec![ResourceMemory::new_dedicated(memory)];
if let Some(image) = image.bind_memory(allocations).ok() {
Some(Arc::new(image))
} else {
None
}
}
pub fn render_texture(&self, width: u32, height: u32, format: Format) -> Arc<Image> {
Image::new(
self.memory_allocator.clone(),
ImageCreateInfo {
image_type: ImageType::Dim2d,
format,
extent: [width, height, 1],
usage: ImageUsage::TRANSFER_SRC
| ImageUsage::SAMPLED
| ImageUsage::COLOR_ATTACHMENT,
..Default::default()
},
AllocationCreateInfo::default(),
)
.unwrap()
}
pub fn create_pipeline(
self: &Arc<Self>,
render_target: Arc<ImageView>,
vert: Arc<ShaderModule>,
frag: Arc<ShaderModule>,
format: Format,
) -> Arc<WlxPipeline> {
Arc::new(WlxPipeline::new(self.clone(), vert, frag, format))
Arc::new(WlxPipeline::new(
render_target,
self.clone(),
vert,
frag,
format,
))
}
pub fn create_command_buffer(
pub fn create_pipeline_with_layouts(
self: &Arc<Self>,
usage: CommandBufferUsage,
) -> WlxCommandBuffer<PrimaryAutoCommandBuffer> {
render_target: Arc<ImageView>,
vert: Arc<ShaderModule>,
frag: Arc<ShaderModule>,
format: Format,
initial_layout: ImageLayout,
final_layout: ImageLayout,
) -> Arc<WlxPipeline> {
Arc::new(WlxPipeline::new_with_layout(
render_target,
self.clone(),
vert,
frag,
format,
initial_layout,
final_layout,
))
}
pub fn create_command_buffer(self: &Arc<Self>, usage: CommandBufferUsage) -> WlxCommandBuffer {
let command_buffer = AutoCommandBufferBuilder::primary(
&self.command_buffer_allocator,
self.queue.queue_family_index(),
@@ -482,31 +587,25 @@ impl WlxGraphics {
..ImageMemoryBarrier::image(image)
};
let builder_alloc = self
.command_buffer_allocator
.allocate(
self.queue.queue_family_index(),
CommandBufferLevel::Primary,
1,
)
.unwrap()
.next()
.unwrap();
let command_buffer = unsafe {
let mut builder = UnsafeCommandBufferBuilder::new(
&builder_alloc.inner(),
&self.command_buffer_allocator,
self.queue.queue_family_index(),
CommandBufferLevel::Primary,
CommandBufferBeginInfo {
usage: CommandBufferUsage::OneTimeSubmit,
inheritance_info: None,
..Default::default()
},
)
.unwrap();
builder.pipeline_barrier(&DependencyInfo {
image_memory_barriers: smallvec![barrier],
..Default::default()
});
builder
.pipeline_barrier(&DependencyInfo {
image_memory_barriers: smallvec![barrier],
..Default::default()
})
.unwrap();
builder.build().unwrap()
};
@@ -535,24 +634,27 @@ impl WlxGraphics {
}
}
pub struct WlxCommandBuffer<T> {
pub struct WlxCommandBuffer {
graphics: Arc<WlxGraphics>,
command_buffer: AutoCommandBufferBuilder<T, Arc<StandardCommandBufferAllocator>>,
command_buffer: AutoCommandBufferBuilder<
PrimaryAutoCommandBuffer<Arc<StandardCommandBufferAllocator>>,
Arc<StandardCommandBufferAllocator>,
>,
}
impl<T> WlxCommandBuffer<T> {
pub fn begin(mut self, render_target: Arc<dyn ImageViewAbstract>) -> Self {
impl WlxCommandBuffer {
pub fn begin_render_pass(mut self, pipeline: &WlxPipeline) -> Self {
self.command_buffer
.begin_rendering(RenderingInfo {
contents: SubpassContents::SecondaryCommandBuffers,
color_attachments: vec![Some(RenderingAttachmentInfo {
load_op: LoadOp::Clear,
store_op: StoreOp::Store,
clear_value: Some([0.0, 0.0, 0.0, 0.0].into()),
..RenderingAttachmentInfo::image_view(render_target.clone())
})],
..Default::default()
})
.begin_render_pass(
RenderPassBeginInfo {
clear_values: vec![Some([0.0, 0.0, 0.0, 1.0].into())],
..RenderPassBeginInfo::framebuffer(pipeline.framebuffer.clone())
},
SubpassBeginInfo {
contents: SubpassContents::SecondaryCommandBuffers,
..Default::default()
},
)
.unwrap();
self
}
@@ -571,26 +673,46 @@ impl<T> WlxCommandBuffer<T> {
height: u32,
format: Format,
data: Vec<u8>,
) -> Arc<ImmutableImage> {
let dimensions = ImageDimensions::Dim2d {
width,
height,
array_layers: 1,
};
ImmutableImage::from_iter(
&self.graphics.memory_allocator,
data,
dimensions,
MipmapsCount::Log2, // required for TRANSFER_SRC
format,
&mut self.command_buffer,
) -> Arc<Image> {
let image = Image::new(
self.graphics.memory_allocator.clone(),
ImageCreateInfo {
image_type: ImageType::Dim2d,
format,
extent: [width, height, 1],
usage: ImageUsage::TRANSFER_DST | ImageUsage::TRANSFER_SRC | ImageUsage::SAMPLED,
..Default::default()
},
AllocationCreateInfo::default(),
)
.unwrap()
.unwrap();
let buffer: Subbuffer<[u8]> = Buffer::new_slice(
self.graphics.memory_allocator.clone(),
BufferCreateInfo {
usage: BufferUsage::TRANSFER_SRC,
..Default::default()
},
AllocationCreateInfo {
memory_type_filter: MemoryTypeFilter::PREFER_HOST
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
..Default::default()
},
data.len() as DeviceSize,
)
.unwrap();
buffer.write().unwrap().copy_from_slice(data.as_slice());
self.command_buffer
.copy_buffer_to_image(CopyBufferToImageInfo::buffer_image(buffer, image.clone()))
.unwrap();
image
}
#[allow(dead_code)]
pub fn texture2d_png(&mut self, bytes: Vec<u8>) -> Arc<ImmutableImage> {
pub fn texture2d_png(&mut self, bytes: Vec<u8>) -> Arc<Image> {
let cursor = Cursor::new(bytes);
let decoder = png::Decoder::new(cursor);
let mut reader = decoder.read_info().unwrap();
@@ -604,13 +726,15 @@ impl<T> WlxCommandBuffer<T> {
}
}
impl WlxCommandBuffer<PrimaryAutoCommandBuffer> {
pub fn end_render(mut self) -> Self {
self.command_buffer.end_rendering().unwrap();
impl WlxCommandBuffer {
pub fn end_render_pass(mut self) -> Self {
self.command_buffer
.end_render_pass(SubpassEndInfo::default())
.unwrap();
self
}
pub fn build(self) -> PrimaryAutoCommandBuffer {
pub fn build(self) -> Arc<PrimaryAutoCommandBuffer<Arc<StandardCommandBufferAllocator>>> {
self.command_buffer.build().unwrap()
}
@@ -629,11 +753,79 @@ impl WlxCommandBuffer<PrimaryAutoCommandBuffer> {
pub struct WlxPipeline {
pub graphics: Arc<WlxGraphics>,
pub pipeline: Arc<GraphicsPipeline>,
pub render_pass: Arc<RenderPass>,
pub framebuffer: Arc<Framebuffer>,
pub view: Arc<ImageView>,
pub format: Format,
}
impl WlxPipeline {
fn new(
render_target: Arc<ImageView>,
graphics: Arc<WlxGraphics>,
vert: Arc<ShaderModule>,
frag: Arc<ShaderModule>,
format: Format,
) -> Self {
let render_pass = vulkano::single_pass_renderpass!(
graphics.device.clone(),
attachments: {
color: {
format: format,
samples: 1,
load_op: Clear,
store_op: Store,
},
},
pass: {
color: [color],
depth_stencil: {},
},
)
.unwrap();
Self::new_from_pass(render_target, render_pass, graphics, vert, frag, format)
}
fn new_with_layout(
render_target: Arc<ImageView>,
graphics: Arc<WlxGraphics>,
vert: Arc<ShaderModule>,
frag: Arc<ShaderModule>,
format: Format,
initial_layout: ImageLayout,
final_layout: ImageLayout,
) -> Self {
let render_pass_description = RenderPassCreateInfo {
attachments: vec![AttachmentDescription {
format: format,
samples: SampleCount::Sample1,
load_op: AttachmentLoadOp::Clear,
store_op: AttachmentStoreOp::Store,
initial_layout,
final_layout,
..Default::default()
}],
subpasses: vec![SubpassDescription {
color_attachments: vec![Some(AttachmentReference {
attachment: 0,
layout: ImageLayout::ColorAttachmentOptimal,
..Default::default()
})],
..Default::default()
}],
..Default::default()
};
let render_pass =
RenderPass::new(graphics.device.clone(), render_pass_description).unwrap();
Self::new_from_pass(render_target, render_pass, graphics, vert, frag, format)
}
fn new_from_pass(
render_target: Arc<ImageView>,
render_pass: Arc<RenderPass>,
graphics: Arc<WlxGraphics>,
vert: Arc<ShaderModule>,
frag: Arc<ShaderModule>,
@@ -641,24 +833,64 @@ impl WlxPipeline {
) -> Self {
let vep = vert.entry_point("main").unwrap();
let fep = frag.entry_point("main").unwrap();
let pipeline = GraphicsPipeline::start()
.render_pass(PipelineRenderingCreateInfo {
color_attachment_formats: vec![Some(format)],
..Default::default()
})
.color_blend_state(ColorBlendState::default().blend(AttachmentBlend::alpha()))
.vertex_input_state(Vert2Uv::per_vertex())
.input_assembly_state(InputAssemblyState::new())
.vertex_shader(vep, ())
.viewport_state(ViewportState::viewport_dynamic_scissor_irrelevant())
.fragment_shader(fep, ())
.build(graphics.device.clone())
let vertex_input_state = Vert2Uv::per_vertex()
.definition(&vep.info().input_interface)
.unwrap();
let stages = smallvec![
PipelineShaderStageCreateInfo::new(vep),
PipelineShaderStageCreateInfo::new(fep),
];
let layout = PipelineLayout::new(
graphics.device.clone(),
PipelineDescriptorSetLayoutCreateInfo::from_stages(&stages)
.into_pipeline_layout_create_info(graphics.device.clone())
.unwrap(),
)
.unwrap();
let framebuffer = Framebuffer::new(
render_pass.clone(),
FramebufferCreateInfo {
attachments: vec![render_target.clone()],
..Default::default()
},
)
.unwrap();
let pipeline = GraphicsPipeline::new(
graphics.device.clone(),
None,
GraphicsPipelineCreateInfo {
stages,
vertex_input_state: Some(vertex_input_state),
input_assembly_state: Some(InputAssemblyState::default()),
viewport_state: Some(ViewportState::default()),
color_blend_state: Some(ColorBlendState {
attachments: vec![ColorBlendAttachmentState {
blend: Some(AttachmentBlend::alpha()),
..Default::default()
}],
..Default::default()
}),
rasterization_state: Some(RasterizationState::default()),
multisample_state: Some(MultisampleState::default()),
dynamic_state: [DynamicState::Viewport].into_iter().collect(),
subpass: Some(Subpass::from(render_pass.clone(), 0).unwrap().into()),
..GraphicsPipelineCreateInfo::layout(layout)
},
)
.unwrap();
Self {
graphics,
pipeline,
format,
render_pass,
framebuffer,
view: render_target,
}
}
@@ -669,7 +901,7 @@ impl WlxPipeline {
pub fn uniform_sampler(
&self,
set: usize,
texture: Arc<dyn ImageViewAbstract>,
texture: Arc<ImageView>,
filter: Filter,
) -> Arc<PersistentDescriptorSet> {
let sampler = Sampler::new(
@@ -689,6 +921,7 @@ impl WlxPipeline {
&self.graphics.descriptor_set_allocator,
layout.clone(),
[WriteDescriptorSet::image_view_sampler(0, texture, sampler)],
[],
)
.unwrap()
}
@@ -701,6 +934,8 @@ impl WlxPipeline {
self.graphics.memory_allocator.clone(),
SubbufferAllocatorCreateInfo {
buffer_usage: BufferUsage::UNIFORM_BUFFER,
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
..Default::default()
},
);
@@ -716,6 +951,7 @@ impl WlxPipeline {
&self.graphics.descriptor_set_allocator,
layout.clone(),
[WriteDescriptorSet::buffer(0, uniform_buffer_subbuffer)],
[],
)
.unwrap()
}
@@ -743,7 +979,7 @@ pub struct WlxPass {
vertex_buffer: Subbuffer<[Vert2Uv]>,
index_buffer: Subbuffer<[u16]>,
descriptor_sets: Vec<Arc<PersistentDescriptorSet>>,
pub command_buffer: Arc<SecondaryAutoCommandBuffer>,
pub command_buffer: Arc<SecondaryAutoCommandBuffer<Arc<StandardCommandBufferAllocator>>>,
}
impl WlxPass {
@@ -755,9 +991,9 @@ impl WlxPass {
descriptor_sets: Vec<Arc<PersistentDescriptorSet>>,
) -> Self {
let viewport = Viewport {
origin: [0.0, 0.0],
dimensions,
depth_range: 0.0..1.0,
offset: [0.0, 0.0],
extent: dimensions,
depth_range: 0.0..=1.0,
};
let pipeline_inner = pipeline.inner().clone();
@@ -766,10 +1002,10 @@ impl WlxPass {
pipeline.graphics.queue.queue_family_index(),
CommandBufferUsage::MultipleSubmit,
CommandBufferInheritanceInfo {
render_pass: Some(CommandBufferInheritanceRenderPassType::BeginRendering(
CommandBufferInheritanceRenderingInfo {
color_attachment_formats: vec![Some(pipeline.format)],
..Default::default()
render_pass: Some(CommandBufferInheritanceRenderPassType::BeginRenderPass(
CommandBufferInheritanceRenderPassInfo {
subpass: Subpass::from(pipeline.render_pass.clone(), 0).unwrap(),
framebuffer: None,
},
)),
..Default::default()
@@ -778,16 +1014,21 @@ impl WlxPass {
.unwrap();
command_buffer
.set_viewport(0, [viewport])
.set_viewport(0, smallvec![viewport])
.unwrap()
.bind_pipeline_graphics(pipeline_inner)
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Graphics,
pipeline.inner().layout().clone(),
0,
descriptor_sets.clone(),
)
.unwrap()
.bind_vertex_buffers(0, vertex_buffer.clone())
.unwrap()
.bind_index_buffer(index_buffer.clone())
.unwrap()
.draw_indexed(index_buffer.len() as u32, 1, 0, 0, 0)
.or_else(|err| {
if let Some(source) = err.source() {
@@ -802,7 +1043,7 @@ impl WlxPass {
vertex_buffer,
index_buffer,
descriptor_sets,
command_buffer: Arc::new(command_buffer.build().unwrap()),
command_buffer: command_buffer.build().unwrap(),
}
}
}