Add third subpass
This commit is contained in:
parent
de0a2bca70
commit
775bda1d07
3 changed files with 294 additions and 162 deletions
|
@ -55,6 +55,20 @@ impl<T> TargetMode<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn chain<'a, R>(&'a self, other: &'a TargetMode<R>) -> TargetMode<(&'a T, &'a R)> {
|
||||||
|
match (self, other) {
|
||||||
|
(TargetMode::Mono(mono_self), TargetMode::Mono(mono_other)) => {
|
||||||
|
TargetMode::Mono((mono_self, mono_other))
|
||||||
|
}
|
||||||
|
(
|
||||||
|
TargetMode::Stereo(left_self, right_self),
|
||||||
|
TargetMode::Stereo(left_other, right_other),
|
||||||
|
) => TargetMode::Stereo((left_self, left_other), (right_self, right_other)),
|
||||||
|
|
||||||
|
_ => panic!("Incompatible TargetModes"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn execute<F, R>(&self, mut f: F) -> anyhow::Result<TargetMode<R>>
|
pub fn execute<F, R>(&self, mut f: F) -> anyhow::Result<TargetMode<R>>
|
||||||
where
|
where
|
||||||
F: FnMut(&T) -> anyhow::Result<R>,
|
F: FnMut(&T) -> anyhow::Result<R>,
|
||||||
|
@ -64,8 +78,52 @@ impl<T> TargetMode<T> {
|
||||||
TargetMode::Stereo(l, r) => TargetMode::Stereo(f(l)?, f(r)?),
|
TargetMode::Stereo(l, r) => TargetMode::Stereo(f(l)?, f(r)?),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn execute_into<F, R>(self, mut f: F) -> anyhow::Result<TargetMode<R>>
|
||||||
|
where
|
||||||
|
F: FnMut(T) -> anyhow::Result<R>,
|
||||||
|
{
|
||||||
|
Ok(match self {
|
||||||
|
TargetMode::Mono(s) => TargetMode::Mono(f(s)?),
|
||||||
|
TargetMode::Stereo(l, r) => TargetMode::Stereo(f(l)?, f(r)?),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait Unfold {
|
||||||
|
type Output;
|
||||||
|
|
||||||
|
fn unfold(self) -> Self::Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_unfold {
|
||||||
|
([<$($var:ident: $type:ident,)+>, $rhs_var:ident: $rhs_type:ident]) => {
|
||||||
|
paste::paste! {
|
||||||
|
impl<'a, $($type,)+ $rhs_type: 'a> Unfold for TargetMode<(&'a ($($type,)+), &'a $rhs_type)> {
|
||||||
|
type Output = TargetMode<($(&'a $type,)+ &'a $rhs_type)>;
|
||||||
|
|
||||||
|
fn unfold(self) -> Self::Output {
|
||||||
|
match self {
|
||||||
|
TargetMode::Mono( (($($var,)+), $rhs_var) ) => TargetMode::Mono(($($var,)+ &$rhs_var)),
|
||||||
|
TargetMode::Stereo( ( ( $( [<l_ $var>], )+ ) , [<l_ $rhs_var>] ), ( ( $( [<r_ $var>], )+ ) , [<r_ $rhs_var>] ) )
|
||||||
|
=> TargetMode::Stereo( ( $( [<l_ $var>], )+ &[<l_ $rhs_var>] ), ( $( [<r_ $var>], )+ &[<r_ $rhs_var>] ) ),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_unfold!([<t: T, r: R,>, s: S]);
|
||||||
|
impl_unfold!([<t: T, r: R, u: U,>, s: S]);
|
||||||
|
impl_unfold!([<t: T, r: R, u: U, v: V,>, s: S]);
|
||||||
|
impl_unfold!([<t: T, r: R, u: U, v: V, w: W,>, s: S]);
|
||||||
|
impl_unfold!([<t: T, r: R, u: U, v: V, w: W, x: X,>, s: S]);
|
||||||
|
impl_unfold!([<t: T, r: R, u: U, v: V, w: W, x: X, y: Y,>, s: S]);
|
||||||
|
impl_unfold!([<t: T, r: R, u: U, v: V, w: W, x: X, y: Y, z: Z,>, s: S]);
|
||||||
|
impl_unfold!([<t: T, r: R, u: U, v: V, w: W, x: X, y: Y, z: Z, q: Q,>, s: S]);
|
||||||
|
|
||||||
impl<T: Clone> Clone for TargetMode<T> {
|
impl<T: Clone> Clone for TargetMode<T> {
|
||||||
fn clone(&self) -> TargetMode<T> {
|
fn clone(&self) -> TargetMode<T> {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -3,14 +3,14 @@ use anyhow::Result;
|
||||||
use assetpath::AssetPath;
|
use assetpath::AssetPath;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use utilities::prelude::*;
|
use utilities::prelude::*;
|
||||||
use vulkan_rs::prelude::*;
|
use vulkan_rs::{prelude::*, render_target::sub_pass::InputAttachmentInfo};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
elements::Elements,
|
elements::Elements,
|
||||||
gui::{iconizable::IconBuilderType, texturedvertex::TexturedVertex},
|
gui::{iconizable::IconBuilderType, texturedvertex::TexturedVertex},
|
||||||
};
|
};
|
||||||
|
|
||||||
use cgmath::ortho;
|
use cgmath::{ortho, vec2, vec4};
|
||||||
|
|
||||||
use std::sync::Weak;
|
use std::sync::Weak;
|
||||||
use std::sync::{
|
use std::sync::{
|
||||||
|
@ -78,7 +78,7 @@ impl<'a> GuiHandlerCreateInfo<'a> {
|
||||||
struct GuiSeparator {
|
struct GuiSeparator {
|
||||||
_descriptor_layout: Arc<DescriptorSetLayout>,
|
_descriptor_layout: Arc<DescriptorSetLayout>,
|
||||||
|
|
||||||
_pipeline: Arc<Pipeline>,
|
pipeline: Arc<Pipeline>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DisplayableTexture {
|
struct DisplayableTexture {
|
||||||
|
@ -96,11 +96,98 @@ struct TextableColor {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CommandBufferState {
|
struct CommandBufferState {
|
||||||
command_buffer: Arc<CommandBuffer>,
|
|
||||||
valid: AtomicBool,
|
|
||||||
text_buffers: RwLock<Vec<Arc<Buffer<TexturedVertex>>>>,
|
text_buffers: RwLock<Vec<Arc<Buffer<TexturedVertex>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct TextToScreen {
|
||||||
|
pipeline: TargetMode<GuiSeparator>,
|
||||||
|
descriptor: TargetMode<Arc<DescriptorSet>>,
|
||||||
|
buffer: Arc<Buffer<TexturedVertex>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TextToScreen {
|
||||||
|
fn new(
|
||||||
|
device: &Arc<Device>,
|
||||||
|
pipeline: TargetMode<GuiSeparator>,
|
||||||
|
render_target: &TargetMode<RwLock<RenderTarget>>,
|
||||||
|
) -> Result<Self> {
|
||||||
|
let descriptor = pipeline
|
||||||
|
.chain(render_target)
|
||||||
|
.execute(|(separator, render_target)| {
|
||||||
|
let descriptor = DescriptorPool::builder()
|
||||||
|
.set_layout(separator._descriptor_layout.clone())
|
||||||
|
.build(device.clone())?
|
||||||
|
.prepare_set()
|
||||||
|
.allocate()?;
|
||||||
|
|
||||||
|
Self::update_descriptor(&descriptor, &*render_target.read().unwrap())?;
|
||||||
|
|
||||||
|
Ok(descriptor)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let edges = [
|
||||||
|
TexturedVertex {
|
||||||
|
position: vec4(-1.0, -1.0, 0.0, 1.0),
|
||||||
|
texture_coordinates: vec2(0.0, 0.0),
|
||||||
|
},
|
||||||
|
TexturedVertex {
|
||||||
|
position: vec4(-1.0, 1.0, 0.0, 1.0),
|
||||||
|
texture_coordinates: vec2(0.0, 1.0),
|
||||||
|
},
|
||||||
|
TexturedVertex {
|
||||||
|
position: vec4(1.0, 1.0, 0.0, 1.0),
|
||||||
|
texture_coordinates: vec2(1.0, 1.0),
|
||||||
|
},
|
||||||
|
TexturedVertex {
|
||||||
|
position: vec4(1.0, 1.0, 0.0, 1.0),
|
||||||
|
texture_coordinates: vec2(1.0, 1.0),
|
||||||
|
},
|
||||||
|
TexturedVertex {
|
||||||
|
position: vec4(1.0, -1.0, 0.0, 1.0),
|
||||||
|
texture_coordinates: vec2(1.0, 0.0),
|
||||||
|
},
|
||||||
|
TexturedVertex {
|
||||||
|
position: vec4(-1.0, -1.0, 0.0, 1.0),
|
||||||
|
texture_coordinates: vec2(0.0, 0.0),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let buffer = Buffer::builder()
|
||||||
|
.set_usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
|
||||||
|
.set_memory_usage(MemoryUsage::CpuOnly)
|
||||||
|
.set_data(&edges)
|
||||||
|
.build(device.clone())?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
pipeline,
|
||||||
|
descriptor,
|
||||||
|
buffer,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_descriptor(
|
||||||
|
descriptor: &Arc<DescriptorSet>,
|
||||||
|
render_target: &RenderTarget,
|
||||||
|
) -> Result<()> {
|
||||||
|
// take resolve target of second sub pass as image sampler
|
||||||
|
descriptor.update(&[DescriptorWrite::input_attachments(
|
||||||
|
0,
|
||||||
|
&[&render_target.sub_pass(1).attachments()[1].image(0)],
|
||||||
|
)
|
||||||
|
.change_image_layout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_on_resize(&self, render_target: &TargetMode<RwLock<RenderTarget>>) -> Result<()> {
|
||||||
|
self.descriptor
|
||||||
|
.chain(render_target)
|
||||||
|
.execute(|(descriptor, render_target)| {
|
||||||
|
Self::update_descriptor(descriptor, &*render_target.read().unwrap())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct GuiHandler {
|
pub struct GuiHandler {
|
||||||
context: Arc<dyn ContextInterface>,
|
context: Arc<dyn ContextInterface>,
|
||||||
|
|
||||||
|
@ -122,6 +209,8 @@ pub struct GuiHandler {
|
||||||
rectangle_objects: TargetMode<GuiSeparator>,
|
rectangle_objects: TargetMode<GuiSeparator>,
|
||||||
single_color_objects: TargetMode<GuiSeparator>,
|
single_color_objects: TargetMode<GuiSeparator>,
|
||||||
|
|
||||||
|
text_to_screen: TextToScreen,
|
||||||
|
|
||||||
_bitmap_font: Arc<Image>,
|
_bitmap_font: Arc<Image>,
|
||||||
_bitmap_desc_pool: Arc<DescriptorPool>,
|
_bitmap_desc_pool: Arc<DescriptorPool>,
|
||||||
bitmap_desc_set: Arc<DescriptorSet>,
|
bitmap_desc_set: Arc<DescriptorSet>,
|
||||||
|
@ -174,19 +263,9 @@ impl GuiHandler {
|
||||||
let device = context.device();
|
let device = context.device();
|
||||||
let queue = context.queue();
|
let queue = context.queue();
|
||||||
|
|
||||||
let command_buffers = match context.images() {
|
let command_buffers = context
|
||||||
TargetMode::Mono(_) => {
|
.images()
|
||||||
let command_buffers = Self::create_command_buffers(device, queue, context)?;
|
.execute(|_| Self::create_command_buffers(context.image_count()))?;
|
||||||
|
|
||||||
TargetMode::Mono(command_buffers)
|
|
||||||
}
|
|
||||||
TargetMode::Stereo(_, _) => {
|
|
||||||
let left_command_buffers = Self::create_command_buffers(device, queue, context)?;
|
|
||||||
let right_command_buffers = Self::create_command_buffers(device, queue, context)?;
|
|
||||||
|
|
||||||
TargetMode::Stereo(left_command_buffers, right_command_buffers)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let text_sample_count = device.max_supported_sample_count(VK_SAMPLE_COUNT_4_BIT);
|
let text_sample_count = device.max_supported_sample_count(VK_SAMPLE_COUNT_4_BIT);
|
||||||
|
|
||||||
|
@ -198,6 +277,12 @@ impl GuiHandler {
|
||||||
let rect_objs = Self::init_rectangle_objects(device, &render_targets)?;
|
let rect_objs = Self::init_rectangle_objects(device, &render_targets)?;
|
||||||
let single_color_objects = Self::init_single_color_objects(device, &render_targets)?;
|
let single_color_objects = Self::init_single_color_objects(device, &render_targets)?;
|
||||||
|
|
||||||
|
let text_to_screen = TextToScreen::new(
|
||||||
|
device,
|
||||||
|
Self::init_text_screen_objects(device, &render_targets)?,
|
||||||
|
&render_targets,
|
||||||
|
)?;
|
||||||
|
|
||||||
let (bitmap_texture, bitmap_desc_pool, bitmap_desc_set) = Self::init_bitmap_font(
|
let (bitmap_texture, bitmap_desc_pool, bitmap_desc_set) = Self::init_bitmap_font(
|
||||||
device,
|
device,
|
||||||
queue,
|
queue,
|
||||||
|
@ -271,6 +356,8 @@ impl GuiHandler {
|
||||||
rectangle_objects: rect_objs,
|
rectangle_objects: rect_objs,
|
||||||
single_color_objects,
|
single_color_objects,
|
||||||
|
|
||||||
|
text_to_screen,
|
||||||
|
|
||||||
_bitmap_font: bitmap_texture,
|
_bitmap_font: bitmap_texture,
|
||||||
_bitmap_desc_pool: bitmap_desc_pool,
|
_bitmap_desc_pool: bitmap_desc_pool,
|
||||||
bitmap_desc_set,
|
bitmap_desc_set,
|
||||||
|
@ -787,6 +874,8 @@ impl GuiHandler {
|
||||||
single_color_objects: &GuiSeparator,
|
single_color_objects: &GuiSeparator,
|
||||||
rectangle_objects: &GuiSeparator,
|
rectangle_objects: &GuiSeparator,
|
||||||
text_objects: &GuiSeparator,
|
text_objects: &GuiSeparator,
|
||||||
|
text_to_screen: &GuiSeparator,
|
||||||
|
text_to_screen_desc: &Arc<DescriptorSet>,
|
||||||
index: usize,
|
index: usize,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let viewport = [VkViewport {
|
let viewport = [VkViewport {
|
||||||
|
@ -812,7 +901,7 @@ impl GuiHandler {
|
||||||
render_target.begin(buffer_recorder, VK_SUBPASS_CONTENTS_INLINE, index);
|
render_target.begin(buffer_recorder, VK_SUBPASS_CONTENTS_INLINE, index);
|
||||||
|
|
||||||
if !elements.is_colorables_empty() {
|
if !elements.is_colorables_empty() {
|
||||||
buffer_recorder.bind_pipeline(&single_color_objects._pipeline)?;
|
buffer_recorder.bind_pipeline(&single_color_objects.pipeline)?;
|
||||||
|
|
||||||
buffer_recorder.set_scissor(&scissor);
|
buffer_recorder.set_scissor(&scissor);
|
||||||
buffer_recorder.set_viewport(&viewport);
|
buffer_recorder.set_viewport(&viewport);
|
||||||
|
@ -828,7 +917,7 @@ impl GuiHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !elements.is_displayables_empty() || !elements.is_iconizables_empty() {
|
if !elements.is_displayables_empty() || !elements.is_iconizables_empty() {
|
||||||
buffer_recorder.bind_pipeline(&rectangle_objects._pipeline)?;
|
buffer_recorder.bind_pipeline(&rectangle_objects.pipeline)?;
|
||||||
|
|
||||||
buffer_recorder.set_scissor(&scissor);
|
buffer_recorder.set_scissor(&scissor);
|
||||||
buffer_recorder.set_viewport(&viewport);
|
buffer_recorder.set_viewport(&viewport);
|
||||||
|
@ -852,10 +941,11 @@ impl GuiHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render_target.next_subpass(buffer_recorder, VK_SUBPASS_CONTENTS_INLINE);
|
// render text, render to offscreen (multisampled) and merge resolved target with actual image
|
||||||
|
|
||||||
if !elements.is_textables_empty() {
|
if !elements.is_textables_empty() {
|
||||||
buffer_recorder.bind_pipeline(&text_objects._pipeline)?;
|
render_target.next_subpass(buffer_recorder, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
|
||||||
|
buffer_recorder.bind_pipeline(&text_objects.pipeline)?;
|
||||||
|
|
||||||
buffer_recorder.set_scissor(&scissor);
|
buffer_recorder.set_scissor(&scissor);
|
||||||
buffer_recorder.set_viewport(&viewport);
|
buffer_recorder.set_viewport(&viewport);
|
||||||
|
@ -878,6 +968,19 @@ impl GuiHandler {
|
||||||
buffer_recorder.draw_complete_single_instance(textable.vertex_count());
|
buffer_recorder.draw_complete_single_instance(textable.vertex_count());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// after text is written und resolved, we read image as input and draw it over the current image
|
||||||
|
render_target.next_subpass(buffer_recorder, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
|
|
||||||
|
buffer_recorder.bind_pipeline(&text_to_screen.pipeline)?;
|
||||||
|
|
||||||
|
buffer_recorder.set_scissor(&scissor);
|
||||||
|
buffer_recorder.set_viewport(&viewport);
|
||||||
|
|
||||||
|
buffer_recorder.bind_descriptor_sets_minimal(&[text_to_screen_desc]);
|
||||||
|
buffer_recorder.bind_vertex_buffer(&self.text_to_screen.buffer);
|
||||||
|
buffer_recorder
|
||||||
|
.draw_complete_single_instance(self.text_to_screen.buffer.size() as u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
render_target.end(buffer_recorder);
|
render_target.end(buffer_recorder);
|
||||||
|
@ -1211,11 +1314,20 @@ impl GuiHandler {
|
||||||
clear_on_load: true,
|
clear_on_load: true,
|
||||||
store_on_save: true,
|
store_on_save: true,
|
||||||
attach_sampler: false,
|
attach_sampler: false,
|
||||||
use_as_input: false,
|
use_as_input: true,
|
||||||
clear_value: ClearValue::Color([0.0, 0.0, 0.0, 0.0]),
|
clear_value: ClearValue::Color([0.0, 0.0, 0.0, 0.0]),
|
||||||
})
|
})
|
||||||
.use_queue(queue.clone())
|
.use_queue(queue.clone())
|
||||||
.build(device)?,
|
.build(device)?,
|
||||||
|
)
|
||||||
|
.add_sub_pass(
|
||||||
|
SubPass::builder(target_images[0].width(), target_images[0].height())
|
||||||
|
.set_input_attachment_info(InputAttachmentInfo {
|
||||||
|
sub_pass_index: 1,
|
||||||
|
input_indices: vec![1],
|
||||||
|
})
|
||||||
|
.set_prepared_targets(target_images, 0, [0.0, 0.0, 0.0, 0.0], false)
|
||||||
|
.build(device)?,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(render_target) = old_render_target {
|
if let Some(render_target) = old_render_target {
|
||||||
|
@ -1225,18 +1337,11 @@ impl GuiHandler {
|
||||||
builder.build(device)
|
builder.build(device)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_command_buffers(
|
fn create_command_buffers(image_count: usize) -> Result<Vec<CommandBufferState>> {
|
||||||
device: &Arc<Device>,
|
let mut command_buffers = Vec::with_capacity(image_count);
|
||||||
queue: &Arc<Mutex<Queue>>,
|
|
||||||
context: &Arc<dyn ContextInterface>,
|
|
||||||
) -> Result<Vec<CommandBufferState>> {
|
|
||||||
let mut command_buffers = Vec::with_capacity(context.image_count());
|
|
||||||
|
|
||||||
for _ in 0..context.image_count() {
|
for _ in 0..image_count {
|
||||||
command_buffers.push(CommandBufferState {
|
command_buffers.push(CommandBufferState {
|
||||||
command_buffer: CommandBuffer::new_secondary()
|
|
||||||
.build(device.clone(), queue.clone())?,
|
|
||||||
valid: AtomicBool::new(false),
|
|
||||||
text_buffers: RwLock::new(Vec::new()),
|
text_buffers: RwLock::new(Vec::new()),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1315,7 +1420,7 @@ impl GuiHandler {
|
||||||
Ok(GuiSeparator {
|
Ok(GuiSeparator {
|
||||||
_descriptor_layout: descriptor_layout.clone(),
|
_descriptor_layout: descriptor_layout.clone(),
|
||||||
|
|
||||||
_pipeline: GuiHandler::init_gui_pipeline(
|
pipeline: GuiHandler::init_gui_pipeline(
|
||||||
device,
|
device,
|
||||||
input_bindings.clone(),
|
input_bindings.clone(),
|
||||||
input_attributes.clone(),
|
input_attributes.clone(),
|
||||||
|
@ -1367,7 +1472,7 @@ impl GuiHandler {
|
||||||
Ok(GuiSeparator {
|
Ok(GuiSeparator {
|
||||||
_descriptor_layout: descriptor_layout.clone(),
|
_descriptor_layout: descriptor_layout.clone(),
|
||||||
|
|
||||||
_pipeline: GuiHandler::init_gui_pipeline(
|
pipeline: GuiHandler::init_gui_pipeline(
|
||||||
device,
|
device,
|
||||||
input_bindings.clone(),
|
input_bindings.clone(),
|
||||||
input_attributes.clone(),
|
input_attributes.clone(),
|
||||||
|
@ -1382,6 +1487,56 @@ impl GuiHandler {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn init_text_screen_objects(
|
||||||
|
device: &Arc<Device>,
|
||||||
|
render_targets: &TargetMode<RwLock<RenderTarget>>,
|
||||||
|
) -> Result<TargetMode<GuiSeparator>> {
|
||||||
|
let descriptor_layout = DescriptorSetLayout::builder()
|
||||||
|
.add_layout_binding(
|
||||||
|
0,
|
||||||
|
VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
|
||||||
|
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
.build(device.clone())?;
|
||||||
|
|
||||||
|
let pipeline_layout = PipelineLayout::builder()
|
||||||
|
.add_descriptor_set_layout(&descriptor_layout)
|
||||||
|
.build(device.clone())?;
|
||||||
|
|
||||||
|
// pipeline creation
|
||||||
|
let vertex_shader = ShaderModule::from_slice(
|
||||||
|
device.clone(),
|
||||||
|
include_bytes!("guishader/rect.vert.spv"),
|
||||||
|
ShaderType::Vertex,
|
||||||
|
)?;
|
||||||
|
let fragment_shader = ShaderModule::from_slice(
|
||||||
|
device.clone(),
|
||||||
|
include_bytes!("guishader/rect.frag.spv"),
|
||||||
|
ShaderType::Fragment,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let (input_bindings, input_attributes) = TexturedVertex::vertex_input_state();
|
||||||
|
|
||||||
|
render_targets.execute(|render_target| {
|
||||||
|
Ok(GuiSeparator {
|
||||||
|
_descriptor_layout: descriptor_layout.clone(),
|
||||||
|
|
||||||
|
pipeline: GuiHandler::init_gui_pipeline(
|
||||||
|
device,
|
||||||
|
input_bindings.clone(),
|
||||||
|
input_attributes.clone(),
|
||||||
|
render_target.read().unwrap().render_pass(),
|
||||||
|
&pipeline_layout,
|
||||||
|
vertex_shader.clone(),
|
||||||
|
fragment_shader.clone(),
|
||||||
|
VK_SAMPLE_COUNT_1_BIT,
|
||||||
|
2,
|
||||||
|
)?,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn init_single_color_objects(
|
fn init_single_color_objects(
|
||||||
device: &Arc<Device>,
|
device: &Arc<Device>,
|
||||||
render_targets: &TargetMode<RwLock<RenderTarget>>,
|
render_targets: &TargetMode<RwLock<RenderTarget>>,
|
||||||
|
@ -1417,7 +1572,7 @@ impl GuiHandler {
|
||||||
Ok(GuiSeparator {
|
Ok(GuiSeparator {
|
||||||
_descriptor_layout: color_layout.clone(),
|
_descriptor_layout: color_layout.clone(),
|
||||||
|
|
||||||
_pipeline: GuiHandler::init_gui_pipeline(
|
pipeline: GuiHandler::init_gui_pipeline(
|
||||||
device,
|
device,
|
||||||
input_bindings.clone(),
|
input_bindings.clone(),
|
||||||
input_attributes.clone(),
|
input_attributes.clone(),
|
||||||
|
@ -1452,32 +1607,6 @@ impl GuiHandler {
|
||||||
.default_rasterization(VK_CULL_MODE_NONE, VK_FRONT_FACE_CLOCKWISE)
|
.default_rasterization(VK_CULL_MODE_NONE, VK_FRONT_FACE_CLOCKWISE)
|
||||||
.build(device.clone(), pipeline_layout, render_pass, sub_pass)
|
.build(device.clone(), pipeline_layout, render_pass, sub_pass)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn select_rendering(
|
|
||||||
&self,
|
|
||||||
buffer_recorder: &mut CommandBufferRecorder<'_>,
|
|
||||||
command_buffer_states: &[CommandBufferState],
|
|
||||||
render_target: &RenderTarget,
|
|
||||||
single_color_objects: &GuiSeparator,
|
|
||||||
rectangle_objects: &GuiSeparator,
|
|
||||||
text_objects: &GuiSeparator,
|
|
||||||
index: usize,
|
|
||||||
) -> Result<()> {
|
|
||||||
let command_buffer_state = &command_buffer_states[index];
|
|
||||||
|
|
||||||
self.render(
|
|
||||||
buffer_recorder,
|
|
||||||
command_buffer_state,
|
|
||||||
render_target,
|
|
||||||
single_color_objects,
|
|
||||||
rectangle_objects,
|
|
||||||
text_objects,
|
|
||||||
index,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GuiHandler {
|
impl GuiHandler {
|
||||||
|
@ -1487,23 +1616,6 @@ impl GuiHandler {
|
||||||
indices: &TargetMode<usize>,
|
indices: &TargetMode<usize>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if self.needs_update.load(SeqCst) {
|
if self.needs_update.load(SeqCst) {
|
||||||
match &self.command_buffers {
|
|
||||||
TargetMode::Mono(command_buffers) => {
|
|
||||||
for state in command_buffers {
|
|
||||||
state.valid.store(false, SeqCst);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TargetMode::Stereo(left_cbs, right_cbs) => {
|
|
||||||
for state in left_cbs {
|
|
||||||
state.valid.store(false, SeqCst);
|
|
||||||
}
|
|
||||||
|
|
||||||
for state in right_cbs {
|
|
||||||
state.valid.store(false, SeqCst);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut text_changes = self.text_change_queue.write().unwrap();
|
let mut text_changes = self.text_change_queue.write().unwrap();
|
||||||
|
|
||||||
if !text_changes.is_empty() {
|
if !text_changes.is_empty() {
|
||||||
|
@ -1517,68 +1629,53 @@ impl GuiHandler {
|
||||||
self.needs_update.store(false, SeqCst);
|
self.needs_update.store(false, SeqCst);
|
||||||
}
|
}
|
||||||
|
|
||||||
match (
|
self.command_buffers
|
||||||
&self.command_buffers,
|
.chain(&self.render_targets)
|
||||||
&self.render_targets,
|
.chain(&self.text_objects)
|
||||||
&self.text_objects,
|
.unfold()
|
||||||
&self.rectangle_objects,
|
.chain(&self.rectangle_objects)
|
||||||
&self.single_color_objects,
|
.unfold()
|
||||||
indices,
|
.chain(&self.single_color_objects)
|
||||||
) {
|
.unfold()
|
||||||
(
|
.chain(indices)
|
||||||
TargetMode::Mono(command_buffers),
|
.unfold()
|
||||||
TargetMode::Mono(render_target),
|
.chain(&self.text_to_screen.pipeline)
|
||||||
TargetMode::Mono(text_objects),
|
.unfold()
|
||||||
TargetMode::Mono(rectangle_objects),
|
.chain(&self.text_to_screen.descriptor)
|
||||||
TargetMode::Mono(single_color_object),
|
.unfold()
|
||||||
TargetMode::Mono(index),
|
.execute(
|
||||||
) => {
|
|(
|
||||||
self.select_rendering(
|
|
||||||
buffer_recorder,
|
|
||||||
command_buffers,
|
command_buffers,
|
||||||
&*render_target.read().unwrap(),
|
render_target,
|
||||||
single_color_object,
|
|
||||||
rectangle_objects,
|
|
||||||
text_objects,
|
text_objects,
|
||||||
*index,
|
rectangle_objects,
|
||||||
)?;
|
single_color_object,
|
||||||
}
|
&&&index,
|
||||||
(
|
text_pipeline,
|
||||||
TargetMode::Stereo(left_cbs, right_cbs),
|
text_descriptor,
|
||||||
TargetMode::Stereo(left_rt, right_rt),
|
)| {
|
||||||
TargetMode::Stereo(left_text_objects, right_text_objects),
|
self.render(
|
||||||
TargetMode::Stereo(left_rectangle_objects, right_rectangle_objects),
|
buffer_recorder,
|
||||||
TargetMode::Stereo(left_single_color_object, right_single_color_object),
|
&command_buffers[index],
|
||||||
TargetMode::Stereo(left_index, right_index),
|
&*render_target.read().unwrap(),
|
||||||
) => {
|
single_color_object,
|
||||||
self.select_rendering(
|
rectangle_objects,
|
||||||
buffer_recorder,
|
text_objects,
|
||||||
left_cbs,
|
text_pipeline,
|
||||||
&*left_rt.read().unwrap(),
|
text_descriptor,
|
||||||
left_single_color_object,
|
index,
|
||||||
left_rectangle_objects,
|
)
|
||||||
left_text_objects,
|
},
|
||||||
*left_index,
|
)?;
|
||||||
)?;
|
|
||||||
self.select_rendering(
|
|
||||||
buffer_recorder,
|
|
||||||
right_cbs,
|
|
||||||
&*right_rt.read().unwrap(),
|
|
||||||
right_single_color_object,
|
|
||||||
right_rectangle_objects,
|
|
||||||
right_text_objects,
|
|
||||||
*right_index,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
_ => panic!("Invalid TargetMode combination"),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resize(&self, width: u32, height: u32) -> Result<()> {
|
pub fn resize(&self, width: u32, height: u32) -> Result<()> {
|
||||||
match (self.context.images(), &self.render_targets) {
|
self.context
|
||||||
(TargetMode::Mono(images), TargetMode::Mono(render_target)) => {
|
.images()
|
||||||
|
.chain(&self.render_targets)
|
||||||
|
.execute(|(images, render_target)| {
|
||||||
let mut rt_lock = render_target.write().unwrap();
|
let mut rt_lock = render_target.write().unwrap();
|
||||||
|
|
||||||
*rt_lock = Self::create_render_target(
|
*rt_lock = Self::create_render_target(
|
||||||
|
@ -1588,34 +1685,11 @@ impl GuiHandler {
|
||||||
&self.queue,
|
&self.queue,
|
||||||
self.text_sample_count,
|
self.text_sample_count,
|
||||||
)?;
|
)?;
|
||||||
}
|
|
||||||
(
|
|
||||||
TargetMode::Stereo(left_images, right_images),
|
|
||||||
TargetMode::Stereo(left_render_target, right_render_target),
|
|
||||||
) => {
|
|
||||||
let mut left_rt_lock = left_render_target.write().unwrap();
|
|
||||||
|
|
||||||
*left_rt_lock = Self::create_render_target(
|
Ok(())
|
||||||
&self.device,
|
})?;
|
||||||
&left_images,
|
|
||||||
Some(&*left_rt_lock),
|
|
||||||
&self.queue,
|
|
||||||
self.text_sample_count,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let mut right_rt_lock = right_render_target.write().unwrap();
|
self.text_to_screen.update_on_resize(&self.render_targets)?;
|
||||||
|
|
||||||
*right_rt_lock = Self::create_render_target(
|
|
||||||
&self.device,
|
|
||||||
&right_images,
|
|
||||||
Some(&*right_rt_lock),
|
|
||||||
&self.queue,
|
|
||||||
self.text_sample_count,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => unreachable!("unsupported case!"),
|
|
||||||
}
|
|
||||||
|
|
||||||
self.needs_update.store(true, SeqCst);
|
self.needs_update.store(true, SeqCst);
|
||||||
*self.ortho.write().unwrap() = ortho(0.0, width as f32, 0.0, height as f32, -1.0, 1.0);
|
*self.ortho.write().unwrap() = ortho(0.0, width as f32, 0.0, height as f32, -1.0, 1.0);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
pub use super::builder::{builder::GuiBuilder, snippet::GuiSnippet};
|
pub use super::builder::{builder::GuiBuilder, snippet::GuiSnippet};
|
||||||
pub use super::context_interface::{ContextInterface, TargetMode};
|
pub use super::context_interface::{ContextInterface, TargetMode, Unfold};
|
||||||
pub use super::controller_button::ControllerButton;
|
pub use super::controller_button::ControllerButton;
|
||||||
pub use super::elements::prelude::*;
|
pub use super::elements::prelude::*;
|
||||||
pub use super::guidirection::GuiDirection;
|
pub use super::guidirection::GuiDirection;
|
||||||
|
|
Loading…
Reference in a new issue