all: remove traditional i3 titlebars, add corner rounding
This commit is contained in:
parent
e1928863d9
commit
a41dbae899
52 changed files with 1866 additions and 1047 deletions
|
|
@ -27,9 +27,14 @@ use {
|
|||
semaphore::VulkanSemaphore,
|
||||
shaders::{
|
||||
ColorManagementData, EotfArgs, FILL_FRAG, FILL_VERT, FillPushConstants,
|
||||
InvEotfArgs, LEGACY_FILL_FRAG, LEGACY_FILL_VERT, LEGACY_TEX_FRAG, LEGACY_TEX_VERT,
|
||||
LegacyFillPushConstants, LegacyTexPushConstants, OUT_FRAG, OUT_VERT,
|
||||
OutPushConstants, TEX_FRAG, TEX_VERT, TexPushConstants, TexVertex, VulkanShader,
|
||||
InvEotfArgs, LEGACY_FILL_FRAG, LEGACY_FILL_VERT, LEGACY_ROUNDED_FILL_FRAG,
|
||||
LEGACY_ROUNDED_FILL_VERT, LEGACY_ROUNDED_TEX_FRAG, LEGACY_ROUNDED_TEX_VERT,
|
||||
LEGACY_TEX_FRAG, LEGACY_TEX_VERT, LegacyFillPushConstants,
|
||||
LegacyRoundedFillPushConstants, LegacyRoundedTexPushConstants,
|
||||
LegacyTexPushConstants, OUT_FRAG, OUT_VERT, OutPushConstants, ROUNDED_FILL_FRAG,
|
||||
ROUNDED_FILL_VERT, ROUNDED_TEX_FRAG, ROUNDED_TEX_VERT, RoundedFillPushConstants,
|
||||
RoundedTexPushConstants, TEX_FRAG, TEX_VERT, TexPushConstants, TexVertex,
|
||||
VulkanShader,
|
||||
},
|
||||
},
|
||||
io_uring::IoUring,
|
||||
|
|
@ -104,6 +109,13 @@ pub struct VulkanRenderer {
|
|||
pub(super) tex_frag_shader: Rc<VulkanShader>,
|
||||
pub(super) out_vert_shader: Option<Rc<VulkanShader>>,
|
||||
pub(super) out_frag_shader: Option<Rc<VulkanShader>>,
|
||||
pub(super) rounded_fill_vert_shader: Rc<VulkanShader>,
|
||||
pub(super) rounded_fill_frag_shader: Rc<VulkanShader>,
|
||||
pub(super) rounded_tex_vert_shader: Rc<VulkanShader>,
|
||||
pub(super) rounded_tex_frag_shader: Rc<VulkanShader>,
|
||||
pub(super) rounded_fill_pipelines: CopyHashMap<vk::Format, FillPipelines>,
|
||||
pub(super) rounded_tex_pipelines:
|
||||
StaticMap<VulkanEotf, CopyHashMap<vk::Format, Rc<TexPipelines>>>,
|
||||
pub(super) tex_descriptor_set_layouts: ArrayVec<Rc<VulkanDescriptorSetLayout>, 2>,
|
||||
pub(super) out_descriptor_set_layout: Option<Rc<VulkanDescriptorSetLayout>>,
|
||||
pub(super) defunct: Cell<bool>,
|
||||
|
|
@ -202,6 +214,8 @@ type Point = [[f32; 2]; 4];
|
|||
enum VulkanOp {
|
||||
Fill(VulkanFillOp),
|
||||
Tex(VulkanTexOp),
|
||||
RoundedFill(VulkanRoundedFillOp),
|
||||
RoundedTex(VulkanRoundedTexOp),
|
||||
}
|
||||
|
||||
struct VulkanTexOp {
|
||||
|
|
@ -231,6 +245,39 @@ struct VulkanFillOp {
|
|||
instances: u32,
|
||||
}
|
||||
|
||||
struct VulkanRoundedFillOp {
|
||||
target: Point,
|
||||
color: [f32; 4],
|
||||
source_type: TexSourceType,
|
||||
size: [f32; 2],
|
||||
corner_radius: [f32; 4],
|
||||
border_width: f32,
|
||||
scale: f32,
|
||||
range_address: DeviceAddress,
|
||||
}
|
||||
|
||||
struct VulkanRoundedTexOp {
|
||||
tex: Rc<VulkanImage>,
|
||||
index: usize,
|
||||
target: Point,
|
||||
source: Point,
|
||||
buffer_resv: Option<Rc<dyn BufferResv>>,
|
||||
acquire_sync: Option<AcquireSync>,
|
||||
release_sync: ReleaseSync,
|
||||
alpha: f32,
|
||||
source_type: TexSourceType,
|
||||
copy_type: TexCopyType,
|
||||
alpha_mode: AlphaMode,
|
||||
tex_cd: Rc<ColorDescription>,
|
||||
color_management_data_address: Option<DeviceAddress>,
|
||||
eotf_args_address: Option<DeviceAddress>,
|
||||
resource_descriptor_buffer_offset: DeviceAddress,
|
||||
size: [f32; 2],
|
||||
corner_radius: [f32; 4],
|
||||
scale: f32,
|
||||
range_address: DeviceAddress,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Linearize, Eq, PartialEq)]
|
||||
pub(super) enum RenderPass {
|
||||
BlendBuffer,
|
||||
|
|
@ -295,12 +342,20 @@ impl VulkanDevice {
|
|||
let tex_frag_shader;
|
||||
let out_vert_shader;
|
||||
let out_frag_shader;
|
||||
let rounded_fill_vert_shader;
|
||||
let rounded_fill_frag_shader;
|
||||
let rounded_tex_vert_shader;
|
||||
let rounded_tex_frag_shader;
|
||||
let mut tex_descriptor_set_layouts = ArrayVec::new();
|
||||
if self.descriptor_buffer.is_some() {
|
||||
tex_vert_shader = self.create_shader(TEX_VERT)?;
|
||||
tex_frag_shader = self.create_shader(TEX_FRAG)?;
|
||||
fill_vert_shader = self.create_shader(FILL_VERT)?;
|
||||
fill_frag_shader = self.create_shader(FILL_FRAG)?;
|
||||
rounded_fill_vert_shader = self.create_shader(ROUNDED_FILL_VERT)?;
|
||||
rounded_fill_frag_shader = self.create_shader(ROUNDED_FILL_FRAG)?;
|
||||
rounded_tex_vert_shader = self.create_shader(ROUNDED_TEX_VERT)?;
|
||||
rounded_tex_frag_shader = self.create_shader(ROUNDED_TEX_FRAG)?;
|
||||
out_vert_shader = Some(self.create_shader(OUT_VERT)?);
|
||||
out_frag_shader = Some(self.create_shader(OUT_FRAG)?);
|
||||
tex_descriptor_set_layouts
|
||||
|
|
@ -311,6 +366,10 @@ impl VulkanDevice {
|
|||
tex_frag_shader = self.create_shader(LEGACY_TEX_FRAG)?;
|
||||
fill_vert_shader = self.create_shader(LEGACY_FILL_VERT)?;
|
||||
fill_frag_shader = self.create_shader(LEGACY_FILL_FRAG)?;
|
||||
rounded_fill_vert_shader = self.create_shader(LEGACY_ROUNDED_FILL_VERT)?;
|
||||
rounded_fill_frag_shader = self.create_shader(LEGACY_ROUNDED_FILL_FRAG)?;
|
||||
rounded_tex_vert_shader = self.create_shader(LEGACY_ROUNDED_TEX_VERT)?;
|
||||
rounded_tex_frag_shader = self.create_shader(LEGACY_ROUNDED_TEX_FRAG)?;
|
||||
out_vert_shader = None;
|
||||
out_frag_shader = None;
|
||||
tex_descriptor_set_layouts
|
||||
|
|
@ -400,6 +459,12 @@ impl VulkanDevice {
|
|||
tex_frag_shader,
|
||||
out_vert_shader,
|
||||
out_frag_shader,
|
||||
rounded_fill_vert_shader,
|
||||
rounded_fill_frag_shader,
|
||||
rounded_tex_vert_shader,
|
||||
rounded_tex_frag_shader,
|
||||
rounded_fill_pipelines: Default::default(),
|
||||
rounded_tex_pipelines: Default::default(),
|
||||
tex_descriptor_set_layouts,
|
||||
out_descriptor_set_layout,
|
||||
defunct: Cell::new(false),
|
||||
|
|
@ -457,6 +522,112 @@ impl VulkanRenderer {
|
|||
Ok(fill_pipelines)
|
||||
}
|
||||
|
||||
fn get_or_create_rounded_fill_pipelines(
|
||||
&self,
|
||||
format: vk::Format,
|
||||
) -> Result<FillPipelines, VulkanError> {
|
||||
if let Some(pl) = self.rounded_fill_pipelines.get(&format) {
|
||||
return Ok(pl);
|
||||
}
|
||||
let create_pipeline = |src_has_alpha| {
|
||||
let push_size = if self.device.descriptor_buffer.is_some() {
|
||||
size_of::<RoundedFillPushConstants>()
|
||||
} else {
|
||||
size_of::<LegacyRoundedFillPushConstants>()
|
||||
};
|
||||
let info = PipelineCreateInfo {
|
||||
format,
|
||||
vert: self.rounded_fill_vert_shader.clone(),
|
||||
frag: self.rounded_fill_frag_shader.clone(),
|
||||
blend: src_has_alpha,
|
||||
src_has_alpha,
|
||||
has_alpha_mult: false,
|
||||
alpha_mode: AlphaMode::PremultipliedOptical,
|
||||
eotf: EOTF_LINEAR,
|
||||
inv_eotf: EOTF_LINEAR,
|
||||
descriptor_set_layouts: Default::default(),
|
||||
has_color_management_data: false,
|
||||
};
|
||||
self.device.create_pipeline2(info, push_size)
|
||||
};
|
||||
let pipelines = Rc::new(static_map! {
|
||||
TexSourceType::HasAlpha => create_pipeline(true)?,
|
||||
TexSourceType::Opaque => create_pipeline(false)?,
|
||||
});
|
||||
self.rounded_fill_pipelines.set(format, pipelines.clone());
|
||||
Ok(pipelines)
|
||||
}
|
||||
|
||||
fn get_or_create_rounded_tex_pipelines(
|
||||
&self,
|
||||
format: vk::Format,
|
||||
target_cd: &ColorDescription,
|
||||
) -> Rc<TexPipelines> {
|
||||
let eotf = target_cd.eotf.to_vulkan();
|
||||
let pipelines = &self.rounded_tex_pipelines[eotf];
|
||||
match pipelines.get(&format) {
|
||||
Some(pl) => pl,
|
||||
_ => {
|
||||
let pl = Rc::new(TexPipelines {
|
||||
format,
|
||||
eotf,
|
||||
pipelines: Default::default(),
|
||||
});
|
||||
pipelines.set(format, pl.clone());
|
||||
pl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_or_create_rounded_tex_pipeline(
|
||||
&self,
|
||||
pipelines: &TexPipelines,
|
||||
tex_cd: &ColorDescription,
|
||||
tex_copy_type: TexCopyType,
|
||||
tex_source_type: TexSourceType,
|
||||
mut tex_alpha_mode: AlphaMode,
|
||||
has_color_management_data: bool,
|
||||
) -> Result<Rc<VulkanPipeline>, VulkanError> {
|
||||
if tex_source_type == TexSourceType::Opaque {
|
||||
tex_alpha_mode = AlphaMode::PremultipliedElectrical;
|
||||
}
|
||||
let key = TexPipelineKey {
|
||||
tex_copy_type,
|
||||
tex_source_type,
|
||||
tex_alpha_mode,
|
||||
eotf: tex_cd.eotf.to_vulkan(),
|
||||
has_color_management_data,
|
||||
};
|
||||
if let Some(pl) = pipelines.pipelines.get(&key) {
|
||||
return Ok(pl);
|
||||
}
|
||||
let has_alpha_mult = match tex_copy_type {
|
||||
TexCopyType::Identity => false,
|
||||
TexCopyType::Multiply => true,
|
||||
};
|
||||
let push_size = if self.device.descriptor_buffer.is_some() {
|
||||
size_of::<RoundedTexPushConstants>()
|
||||
} else {
|
||||
size_of::<LegacyRoundedTexPushConstants>()
|
||||
};
|
||||
let info = PipelineCreateInfo {
|
||||
format: pipelines.format,
|
||||
vert: self.rounded_tex_vert_shader.clone(),
|
||||
frag: self.rounded_tex_frag_shader.clone(),
|
||||
blend: true, // always blend since corners are transparent
|
||||
src_has_alpha: true, // rounding makes everything have alpha
|
||||
has_alpha_mult,
|
||||
alpha_mode: key.tex_alpha_mode,
|
||||
eotf: key.eotf.to_vulkan(),
|
||||
inv_eotf: pipelines.eotf.to_vulkan(),
|
||||
descriptor_set_layouts: self.tex_descriptor_set_layouts.clone(),
|
||||
has_color_management_data,
|
||||
};
|
||||
let pl = self.device.create_pipeline2(info, push_size)?;
|
||||
pipelines.pipelines.set(key, pl.clone());
|
||||
Ok(pl)
|
||||
}
|
||||
|
||||
fn get_or_create_tex_pipelines(
|
||||
&self,
|
||||
format: vk::Format,
|
||||
|
|
@ -665,23 +836,34 @@ impl VulkanRenderer {
|
|||
RenderPass::FrameBuffer => fb_inv_eotf_args_descriptor,
|
||||
};
|
||||
for cmd in &mut memory.ops[pass] {
|
||||
let VulkanOp::Tex(c) = cmd else {
|
||||
continue;
|
||||
let (tex, resource_offset, cm_addr, eotf_addr) = match cmd {
|
||||
VulkanOp::Tex(c) => (
|
||||
&c.tex,
|
||||
&mut c.resource_descriptor_buffer_offset,
|
||||
&c.color_management_data_address,
|
||||
&c.eotf_args_address,
|
||||
),
|
||||
VulkanOp::RoundedTex(c) => (
|
||||
&c.tex,
|
||||
&mut c.resource_descriptor_buffer_offset,
|
||||
&c.color_management_data_address,
|
||||
&c.eotf_args_address,
|
||||
),
|
||||
_ => continue,
|
||||
};
|
||||
let tex = &c.tex;
|
||||
c.resource_descriptor_buffer_offset = resource_writer.next_offset();
|
||||
*resource_offset = resource_writer.next_offset();
|
||||
let mut writer = resource_writer.add_set(tex_descriptor_set_layout);
|
||||
writer.write(
|
||||
tex_descriptor_set_layout.offsets[0],
|
||||
tex.sampled_image_descriptor.as_ref().unwrap(),
|
||||
);
|
||||
if let Some(addr) = c.color_management_data_address {
|
||||
if let Some(addr) = *cm_addr {
|
||||
writer.write(
|
||||
tex_descriptor_set_layout.offsets[1],
|
||||
get_ub_descriptor!(addr, ColorManagementData),
|
||||
);
|
||||
}
|
||||
if let Some(addr) = c.eotf_args_address {
|
||||
if let Some(addr) = *eotf_addr {
|
||||
writer.write(
|
||||
tex_descriptor_set_layout.offsets[2],
|
||||
get_ub_descriptor!(addr, EotfArgs),
|
||||
|
|
@ -741,12 +923,18 @@ impl VulkanRenderer {
|
|||
enum Key {
|
||||
Fill { color: [u32; 4] },
|
||||
Tex(usize),
|
||||
RoundedFill { color: [u32; 4] },
|
||||
RoundedTex(usize),
|
||||
}
|
||||
match o {
|
||||
VulkanOp::Fill(f) => Key::Fill {
|
||||
color: f.color.map(|c| c.to_bits()),
|
||||
},
|
||||
VulkanOp::Tex(t) => Key::Tex(t.index),
|
||||
VulkanOp::RoundedFill(f) => Key::RoundedFill {
|
||||
color: f.color.map(|c| c.to_bits()),
|
||||
},
|
||||
VulkanOp::RoundedTex(t) => Key::RoundedTex(t.index),
|
||||
}
|
||||
});
|
||||
let mops = &mut memory.ops[pass];
|
||||
|
|
@ -782,6 +970,22 @@ impl VulkanRenderer {
|
|||
}
|
||||
mops.push(VulkanOp::Tex(c));
|
||||
}
|
||||
VulkanOp::RoundedFill(mut f) => {
|
||||
f.range_address = memory.data_buffer.len() as DeviceAddress;
|
||||
memory.data_buffer.extend_from_slice(uapi::as_bytes(&f.target));
|
||||
mops.push(VulkanOp::RoundedFill(f));
|
||||
}
|
||||
VulkanOp::RoundedTex(mut c) => {
|
||||
c.range_address = memory.data_buffer.len() as DeviceAddress;
|
||||
let vertex = TexVertex {
|
||||
pos: c.target,
|
||||
tex_pos: c.source,
|
||||
};
|
||||
memory
|
||||
.data_buffer
|
||||
.extend_from_slice(uapi::as_bytes(&vertex));
|
||||
mops.push(VulkanOp::RoundedTex(c));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -917,6 +1121,105 @@ impl VulkanRenderer {
|
|||
}));
|
||||
}
|
||||
}
|
||||
GfxApiOpt::RoundedFillRect(rf) => {
|
||||
let target = rf.rect.to_points();
|
||||
for pass in RenderPass::variants() {
|
||||
let Some(bounds) = memory.paint_bounds[pass] else {
|
||||
continue;
|
||||
};
|
||||
if !bounds.intersects(&target) {
|
||||
continue;
|
||||
}
|
||||
let target_cd = match pass {
|
||||
RenderPass::BlendBuffer => blend_cd,
|
||||
RenderPass::FrameBuffer => fb_cd,
|
||||
};
|
||||
let tf = target_cd.eotf;
|
||||
let color = memory.color_transforms.apply_to_color(
|
||||
&rf.cd,
|
||||
target_cd,
|
||||
rf.render_intent,
|
||||
rf.color,
|
||||
);
|
||||
let color = color.to_array2(tf, rf.alpha);
|
||||
let source_type = TexSourceType::HasAlpha;
|
||||
memory.ops_tmp[pass].push(VulkanOp::RoundedFill(VulkanRoundedFillOp {
|
||||
target,
|
||||
color,
|
||||
source_type,
|
||||
size: rf.size,
|
||||
corner_radius: rf.corner_radius,
|
||||
border_width: rf.border_width,
|
||||
scale: rf.scale,
|
||||
range_address: 0,
|
||||
}));
|
||||
}
|
||||
}
|
||||
GfxApiOpt::RoundedCopyTexture(ct) => {
|
||||
let tex = ct.tex.clone().into_vk(&self.device.device)?;
|
||||
if tex.contents_are_undefined.get() {
|
||||
log::warn!("Ignoring undefined texture");
|
||||
continue;
|
||||
}
|
||||
if tex.queue_state.get().acquire(QueueFamily::Gfx) == QueueTransfer::Impossible
|
||||
{
|
||||
log::warn!("Ignoring texture owned by different queue");
|
||||
continue;
|
||||
}
|
||||
let target = ct.target.to_points();
|
||||
let source = ct.source.to_points();
|
||||
for pass in RenderPass::variants() {
|
||||
let Some(bounds) = memory.paint_bounds[pass] else {
|
||||
continue;
|
||||
};
|
||||
if !bounds.intersects(&target) {
|
||||
continue;
|
||||
}
|
||||
let copy_type = match ct.alpha.is_some() {
|
||||
true => TexCopyType::Multiply,
|
||||
false => TexCopyType::Identity,
|
||||
};
|
||||
let source_type = TexSourceType::HasAlpha;
|
||||
let target_cd = match pass {
|
||||
RenderPass::BlendBuffer => blend_cd,
|
||||
RenderPass::FrameBuffer => fb_cd,
|
||||
};
|
||||
let color_management_data_address = memory.color_transforms.get_offset(
|
||||
&ct.cd.linear,
|
||||
target_cd,
|
||||
ct.render_intent,
|
||||
self.device.uniform_buffer_offset_mask,
|
||||
&mut memory.uniform_buffer_writer,
|
||||
);
|
||||
let eotf_args_address = memory.eotf_args_cache.get_offset(
|
||||
&ct.cd,
|
||||
false,
|
||||
self.device.uniform_buffer_offset_mask,
|
||||
&mut memory.uniform_buffer_writer,
|
||||
);
|
||||
memory.ops_tmp[pass].push(VulkanOp::RoundedTex(VulkanRoundedTexOp {
|
||||
tex: tex.clone(),
|
||||
index,
|
||||
target,
|
||||
source,
|
||||
buffer_resv: ct.buffer_resv.clone(),
|
||||
acquire_sync: Some(ct.acquire_sync.clone()),
|
||||
release_sync: ct.release_sync,
|
||||
alpha: ct.alpha.unwrap_or_default(),
|
||||
source_type,
|
||||
copy_type,
|
||||
alpha_mode: ct.alpha_mode,
|
||||
tex_cd: ct.cd.clone(),
|
||||
color_management_data_address,
|
||||
eotf_args_address,
|
||||
resource_descriptor_buffer_offset: 0,
|
||||
size: ct.size,
|
||||
corner_radius: ct.corner_radius,
|
||||
scale: ct.scale,
|
||||
range_address: 0,
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sync(memory);
|
||||
|
|
@ -998,6 +1301,12 @@ impl VulkanRenderer {
|
|||
VulkanOp::Tex(c) => {
|
||||
c.range_address += buffer.buffer.address;
|
||||
}
|
||||
VulkanOp::RoundedFill(f) => {
|
||||
f.range_address += buffer.buffer.address;
|
||||
}
|
||||
VulkanOp::RoundedTex(c) => {
|
||||
c.range_address += buffer.buffer.address;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1029,9 +1338,16 @@ impl VulkanRenderer {
|
|||
}
|
||||
for ops in memory.ops.values_mut() {
|
||||
for op in ops {
|
||||
if let VulkanOp::Tex(c) = op {
|
||||
adj!(&mut c.color_management_data_address);
|
||||
adj!(&mut c.eotf_args_address);
|
||||
match op {
|
||||
VulkanOp::Tex(c) => {
|
||||
adj!(&mut c.color_management_data_address);
|
||||
adj!(&mut c.eotf_args_address);
|
||||
}
|
||||
VulkanOp::RoundedTex(c) => {
|
||||
adj!(&mut c.color_management_data_address);
|
||||
adj!(&mut c.eotf_args_address);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1051,8 +1367,12 @@ impl VulkanRenderer {
|
|||
let execution = self.allocate_point();
|
||||
for pass in RenderPass::variants() {
|
||||
for cmd in &mut memory.ops[pass] {
|
||||
if let VulkanOp::Tex(c) = cmd {
|
||||
let tex = &c.tex;
|
||||
let tex_data = match cmd {
|
||||
VulkanOp::Tex(c) => Some((&c.tex, &mut c.buffer_resv, &mut c.acquire_sync, c.release_sync)),
|
||||
VulkanOp::RoundedTex(c) => Some((&c.tex, &mut c.buffer_resv, &mut c.acquire_sync, c.release_sync)),
|
||||
_ => None,
|
||||
};
|
||||
if let Some((tex, buffer_resv, acquire_sync, release_sync)) = tex_data {
|
||||
if tex.execution_version.replace(execution) == execution {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1066,9 +1386,9 @@ impl VulkanRenderer {
|
|||
}
|
||||
memory.textures.push(UsedTexture {
|
||||
tex: tex.clone(),
|
||||
resv: c.buffer_resv.take(),
|
||||
acquire_sync: c.acquire_sync.take().unwrap(),
|
||||
release_sync: c.release_sync,
|
||||
resv: buffer_resv.take(),
|
||||
acquire_sync: acquire_sync.take().unwrap(),
|
||||
release_sync,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1301,6 +1621,10 @@ impl VulkanRenderer {
|
|||
let memory = &*self.memory.borrow();
|
||||
let fill_pl = self.get_or_create_fill_pipelines(target.format.vk_format)?;
|
||||
let tex_pl = self.get_or_create_tex_pipelines(target.format.vk_format, target_cd);
|
||||
let rounded_fill_pl =
|
||||
self.get_or_create_rounded_fill_pipelines(target.format.vk_format)?;
|
||||
let rounded_tex_pl =
|
||||
self.get_or_create_rounded_tex_pipelines(target.format.vk_format, target_cd);
|
||||
let dev = &self.device.device;
|
||||
let mut current_pipeline = None;
|
||||
let mut bind = |pipeline: &VulkanPipeline| {
|
||||
|
|
@ -1421,6 +1745,134 @@ impl VulkanRenderer {
|
|||
}
|
||||
}
|
||||
}
|
||||
VulkanOp::RoundedFill(r) => {
|
||||
let pipeline = &rounded_fill_pl[r.source_type];
|
||||
bind(pipeline);
|
||||
if self.device.descriptor_buffer.is_some() {
|
||||
let push = RoundedFillPushConstants {
|
||||
color: r.color,
|
||||
vertices: r.range_address,
|
||||
size: r.size,
|
||||
corner_radius: r.corner_radius,
|
||||
border_width: r.border_width,
|
||||
scale: r.scale,
|
||||
};
|
||||
unsafe {
|
||||
dev.cmd_push_constants(
|
||||
buf,
|
||||
pipeline.pipeline_layout,
|
||||
ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT,
|
||||
0,
|
||||
uapi::as_bytes(&push),
|
||||
);
|
||||
dev.cmd_draw(buf, 4, 1, 0, 0);
|
||||
}
|
||||
} else {
|
||||
let push = LegacyRoundedFillPushConstants {
|
||||
pos: r.target,
|
||||
color: r.color,
|
||||
size_x: r.size[0],
|
||||
size_y: r.size[1],
|
||||
corner_radius_tl: r.corner_radius[0],
|
||||
corner_radius_tr: r.corner_radius[1],
|
||||
corner_radius_br: r.corner_radius[2],
|
||||
corner_radius_bl: r.corner_radius[3],
|
||||
border_width: r.border_width,
|
||||
scale: r.scale,
|
||||
};
|
||||
unsafe {
|
||||
dev.cmd_push_constants(
|
||||
buf,
|
||||
pipeline.pipeline_layout,
|
||||
ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT,
|
||||
0,
|
||||
uapi::as_bytes(&push),
|
||||
);
|
||||
dev.cmd_draw(buf, 4, 1, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
VulkanOp::RoundedTex(c) => {
|
||||
let tex = &c.tex;
|
||||
let pipeline = self.get_or_create_rounded_tex_pipeline(
|
||||
&rounded_tex_pl,
|
||||
&c.tex_cd,
|
||||
c.copy_type,
|
||||
c.source_type,
|
||||
c.alpha_mode,
|
||||
c.color_management_data_address.is_some(),
|
||||
)?;
|
||||
bind(&pipeline);
|
||||
let image_info = DescriptorImageInfo::default()
|
||||
.image_view(tex.texture_view)
|
||||
.image_layout(ImageLayout::SHADER_READ_ONLY_OPTIMAL);
|
||||
if let Some(db) = &self.device.descriptor_buffer {
|
||||
let push = RoundedTexPushConstants {
|
||||
vertices: c.range_address,
|
||||
alpha: c.alpha,
|
||||
size_x: c.size[0],
|
||||
size_y: c.size[1],
|
||||
corner_radius_tl: c.corner_radius[0],
|
||||
corner_radius_tr: c.corner_radius[1],
|
||||
corner_radius_br: c.corner_radius[2],
|
||||
corner_radius_bl: c.corner_radius[3],
|
||||
scale: c.scale,
|
||||
};
|
||||
unsafe {
|
||||
db.cmd_set_descriptor_buffer_offsets(
|
||||
buf,
|
||||
PipelineBindPoint::GRAPHICS,
|
||||
pipeline.pipeline_layout,
|
||||
0,
|
||||
&[0, 1],
|
||||
&[0, c.resource_descriptor_buffer_offset],
|
||||
);
|
||||
dev.cmd_push_constants(
|
||||
buf,
|
||||
pipeline.pipeline_layout,
|
||||
ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT,
|
||||
0,
|
||||
uapi::as_bytes(&push),
|
||||
);
|
||||
dev.cmd_draw(buf, 4, 1, 0, 0);
|
||||
}
|
||||
} else {
|
||||
let write_descriptor_set = WriteDescriptorSet::default()
|
||||
.descriptor_type(DescriptorType::COMBINED_IMAGE_SAMPLER)
|
||||
.image_info(slice::from_ref(&image_info));
|
||||
unsafe {
|
||||
self.device.push_descriptor.cmd_push_descriptor_set(
|
||||
buf,
|
||||
PipelineBindPoint::GRAPHICS,
|
||||
pipeline.pipeline_layout,
|
||||
0,
|
||||
slice::from_ref(&write_descriptor_set),
|
||||
);
|
||||
}
|
||||
let push = LegacyRoundedTexPushConstants {
|
||||
pos: c.target,
|
||||
tex_pos: c.source,
|
||||
alpha: c.alpha,
|
||||
size_x: c.size[0],
|
||||
size_y: c.size[1],
|
||||
corner_radius_tl: c.corner_radius[0],
|
||||
corner_radius_tr: c.corner_radius[1],
|
||||
corner_radius_br: c.corner_radius[2],
|
||||
corner_radius_bl: c.corner_radius[3],
|
||||
scale: c.scale,
|
||||
};
|
||||
unsafe {
|
||||
dev.cmd_push_constants(
|
||||
buf,
|
||||
pipeline.pipeline_layout,
|
||||
ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT,
|
||||
0,
|
||||
uapi::as_bytes(&push),
|
||||
);
|
||||
dev.cmd_draw(buf, 4, 1, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -1933,6 +2385,13 @@ impl VulkanRenderer {
|
|||
};
|
||||
(opaque, c.target)
|
||||
}
|
||||
GfxApiOpt::RoundedFillRect(_) => {
|
||||
// Rounded rects are never fully opaque due to AA at corners
|
||||
continue;
|
||||
}
|
||||
GfxApiOpt::RoundedCopyTexture(_) => {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
if opaque || bb.is_none() {
|
||||
tag |= 1;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue